fix(dashboard): prevent table chart infinite reload loop#36686
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical infinite reload loop in dashboard table charts caused by the clientView property being continuously written to ownState. The fix strips clientView from ownState in the getRelevantDataMask selector, preventing Dashboard from seeing these changes as state updates that trigger re-queries.
Key changes:
- Modified
getRelevantDataMaskto stripclientViewfromownStateusing lodashomit - Added comprehensive unit tests in
activeAllDashboardFilters.test.tscovering the fix and edge cases - Added integration tests in
Dashboard.test.jsxverifying Dashboard behavior with ownDataCharts changes
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
superset-frontend/src/dashboard/util/activeAllDashboardFilters.ts |
Added logic to strip clientView from ownState in the getRelevantDataMask selector, preventing infinite reload loops |
superset-frontend/src/dashboard/util/activeAllDashboardFilters.test.ts |
Added 4 comprehensive test cases covering clientView stripping behavior, equality checks, and verifying other properties remain unchanged |
superset-frontend/src/dashboard/components/Dashboard.test.jsx |
Added 2 integration tests verifying Dashboard correctly handles ownDataCharts updates when clientView changes are filtered out |
The implementation correctly mirrors the existing pattern in ExploreViewContainer (lines 606 and 946) where clientView is already stripped. The fix is minimal, well-tested, and addresses the root cause at the selector level where Dashboard receives state updates.
|
🎪 Showtime deployed environment on GHA for 0770786 • Environment: http://35.92.7.123:8080 (admin/admin) |
0770786 to
b6e572c
Compare
|
🎪 Showtime deployed environment on GHA for 9e6d1c7 • Environment: http://35.86.137.108:8080 (admin/admin) |
| .filter(item => item[prop]) | ||
| .map(item => [item.id, item[prop]]), | ||
| .map(item => { | ||
| const value = item[prop]; |
There was a problem hiding this comment.
Shouldn't this be handled by the chart component instead of getRelevantDataMask? I'm wondering if clientView might be useful for another caller of getRelevantDataMask and should just be discarded by the chart when re-rendering.
There was a problem hiding this comment.
I think modifying the table chart plugin (separate package) to conditionally write clientView based on context could potentially be more complex and could introduce regressions. Also this mirrors how Explore does it
There was a problem hiding this comment.
I think we have two options:
- Given the "relevant" word on
getRelevantDataMask, we might consider thatclientViewis not relevant and your solution would be correct. This means thatclientViewis never relevant for any caller of this function which might be true given that there's only one caller currently (DashboardPage.tsx). - If
clientViewmight be useful for other callers, we could changeDashboardPage.tsxand omit the property there:
const selectRelevantDatamask = createSelector(
(state: RootState) => state.dataMask,
dataMask => omit(getRelevantDataMask(dataMask, 'ownState'), ['clientView']),
);
I'm good with either solution, so I'm approving the PR.
|
OMG THANK YOU. @SBIN2010 and I were just talking about this yesterday... |
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> (cherry picked from commit c026ae2)
|
Hey @rusackas, @sadpandajoe 👋. Do we have an estimate for when this will be released? This has been a real issue for us for a month or so and we'd love to get this out to our teams |
|
Looks like it's on Preset, but for Superset, it'll likely be part of 6.0.1 or 6.1.0, whichever comes first (both are being worked on, but it's a volunteer thing to build/fix/test these releases, so we do our best) |
|
@sadpandajoe might have a more detailed answer. |
SUMMARY
Fixes an infinite reload loop in Dashboard context where table charts would continuously re-query, causing hundreds/thousands of API calls per user.
Root Cause: The recent "Export table data with Search box" feature (PR #36281) added clientView to ownState on every filtered-row change. In Dashboard context, getRelevantDataMask passed this through unchanged, causing Dashboard.jsx to see continuous state changes and trigger re-queries in an infinite loop.
Fix: Strip clientView from ownState in getRelevantDataMask (the selector that extracts chart state for Dashboard). This matches the existing pattern in ExploreViewContainer which already strips clientView before comparing state changes.
Why this location: clientView is explicitly for export functionality, not for triggering re-queries. Stripping at the selector level ensures Dashboard never sees these changes as state updates.
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
TESTING INSTRUCTIONS
ADDITIONAL INFORMATION