Skip to content

fix(matrixify): lazy-load grid cells with dashboard virtualization - #43053

Open
jenwitteng wants to merge 2 commits into
apache:masterfrom
jenwitteng:matrixify-lazy-load-virtualization
Open

fix(matrixify): lazy-load grid cells with dashboard virtualization#43053
jenwitteng wants to merge 2 commits into
apache:masterfrom
jenwitteng:matrixify-lazy-load-virtualization

Conversation

@jenwitteng

Copy link
Copy Markdown
Contributor

SUMMARY

Matrixify grid cells did not participate in the existing DASHBOARD_VIRTUALIZATION mechanism that other dashboard content (Row.tsx) already uses to avoid firing every chart's query at once. As a result, a large Matrixify matrix (e.g. 10x10 = 100 cells) fires 100 chart queries in the same tick regardless of how many cells are actually visible, even with the flag enabled.

This fixes that gap: each Matrixify grid cell now defers mounting its StatefulChart (and therefore its data query) until the cell scrolls into view, using an IntersectionObserver, mirroring the lazy mount/unmount pattern Row.tsx already uses for the same flag - applied at the individual-cell level instead of the row level.

A one-way latch keeps a cell mounted once it has entered the viewport, so scrolling back and forth doesn't cause refetch churn.

Two existing export paths are respected so captures still include the full matrix regardless of scroll position:

  • Server-side screenshot/report/thumbnail workers set navigator.webdriver; cells render immediately in that case.
  • Client-side "Download as Image/PDF" dispatches FORCE_IN_VIEW_EVENT (src/utils/downloadUtils.ts), optionally scoped to a batch of dashboard row ids for large dashboards (forceLoadAllCharts's row-batching). MatrixifyGridCell mirrors the same scoping Row.tsx applies (via the nearest ancestor [data-row-id]), so it only force-mounts when its own row's batch fires (or the dispatch is unscoped). Without this, a Matrixify chart in an already-mounted row would dump every deferred cell's query into whichever batch happens to fire first, defeating the purpose of downloadUtils.ts's row batching.

The event-name constants are duplicated (not imported) from src/dashboard/constants.ts into a new packages/superset-ui-core/.../Matrixify/virtualizationEvents.ts, since packages/superset-ui-core cannot depend on app code under src/dashboard.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A - this changes query timing/count, not visual appearance. Off-screen cells render a same-sized empty placeholder instead of the chart until they scroll into view; there is no visible layout change.

TESTING INSTRUCTIONS

  1. Enable the DASHBOARD_VIRTUALIZATION feature flag.
  2. Create a dashboard with a Matrixify chart whose grid has more rows/columns than fit in the viewport (e.g. a 5x5 or larger grid).
  3. Open the browser Network tab, load the dashboard, and confirm only the cells currently in view (plus a ~200px buffer) fire chart-data requests; scrolling down triggers additional requests only for newly-revealed cells.
  4. Scroll a cell out of view and back - confirm it does not re-fire its query (latch).
  5. With the flag still on, use the dashboard's "Download as Image" or "Download as PDF" action on a dashboard containing this Matrixify chart, and confirm the exported file includes every cell's chart, not blank placeholders for the ones that were off-screen.
  6. Disable the feature flag and confirm all cells render immediately as before (no behavior change).

Unit tests added in MatrixifyGridCell.test.tsx cover: eager rendering with the flag off, deferred mount + IntersectionObserver-triggered mount, the mount latch, headless-capture eager rendering, unscoped and row-scoped FORCE_IN_VIEW_EVENT handling (including a cell mounting for the first time after its row's batch has already fired), and re-arming after RESTORE_VIRTUALIZATION_EVENT.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags: DASHBOARD_VIRTUALIZATION (existing flag; this fixes Matrixify's per-cell rendering to respect it, it does not add a new flag)
  • Changes UI
  • Includes DB Migration
  • Introduces new feature or API
  • Removes existing feature or API

Defer mounting each Matrixify cell's StatefulChart (and therefore its data
query) until the cell scrolls into view, using an IntersectionObserver. This
prevents a large matrix from firing every cell's query at once.

Gated behind the existing DASHBOARD_VIRTUALIZATION feature flag, matching the
lazy-mount/unmount pattern dashboard Row.tsx already uses. A one-way latch
keeps a cell mounted once seen, avoiding refetch churn while scrolling.

Two paths force cells to render eagerly regardless of scroll position, so
exports still capture the full matrix:
- Server-side screenshot/report/thumbnail workers set navigator.webdriver;
  cells render immediately in that case.
- Client-side "Download as Image/PDF" dispatches FORCE_IN_VIEW_EVENT (see
  downloadUtils.ts), optionally scoped to a batch of dashboard row ids for
  large dashboards. MatrixifyGridCell mirrors Row.tsx's own scoping (via the
  nearest ancestor [data-row-id]) so it mounts in step with its own row's
  batch instead of dumping every deferred cell's query into whichever batch
  happens to fire first - which would otherwise defeat the very batching
  downloadUtils.ts uses to avoid a thundering herd of chart queries.
@dosubot dosubot Bot added dashboard:performance Related to Dashboard performance viz:charts Namespace | Anything related to viz types labels Aug 11, 2026

@bito-code-review bito-code-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #637bb7

Actionable Suggestions - 1
  • superset-frontend/packages/superset-ui-core/src/chart/components/Matrixify/MatrixifyGridCell.test.tsx - 1
Additional Suggestions - 1
  • superset-frontend/packages/superset-ui-core/src/chart/components/Matrixify/virtualizationEvents.ts - 1
    • Missing unit tests for isForceInViewActiveForRow · Line 78-78
      The exported `isForceInViewActiveForRow` is called in MatrixifyGridCell.tsx at line 181 but has no direct unit test assertions. It needs tests that cover all three return paths (undefined, null, Set) and the null rowId case per BITO.md rule 6262.
Review Details
  • Files reviewed - 3 · Commit Range: bc3c529..bc3c529
    • superset-frontend/packages/superset-ui-core/src/chart/components/Matrixify/MatrixifyGridCell.test.tsx
    • superset-frontend/packages/superset-ui-core/src/chart/components/Matrixify/MatrixifyGridCell.tsx
    • superset-frontend/packages/superset-ui-core/src/chart/components/Matrixify/virtualizationEvents.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo


expect(screen.getByText('SuperChart Mock')).toBeInTheDocument();
expect(
screen.queryByTestId('matrixify-cell-placeholder'),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data-testid attribute mismatch

The placeholder element at line 265 uses data-test="matrixify-cell-placeholder" but all new tests use screen.getByTestId('matrixify-cell-placeholder') which looks for data-testid. This mismatch will cause every virtualization-related test to fail with: TestingLibraryElementError: Unable to find an accessible element with the test-id: 'matrixify-cell-placeholder'. Fix: change data-test to data-testid on the ChartPlaceholder component in MatrixifyGridCell.tsx:265.

Code Review Run #637bb7


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a false positive: this repo globally remaps RTL's testIdAttribute to 'data-test'
(spec/helpers/setup.ts), which is exactly why StatefulChart.test.tsx uses the same data-test convention elsewhere.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the project's testing setup globally maps data-test to the testIdAttribute used by screen.getByTestId, then this suggestion is indeed a false positive. You can safely ignore this comment, as the existing test convention is consistent with the project's global configuration.

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.55%. Comparing base (34b2d3a) to head (b58f4bb).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #43053   +/-   ##
=======================================
  Coverage   66.55%   66.55%           
=======================================
  Files        2864     2865    +1     
  Lines      161891   161945   +54     
  Branches    37304    37324   +20     
=======================================
+ Hits       107743   107781   +38     
- Misses      52102    52118   +16     
  Partials     2046     2046           
Flag Coverage Δ
javascript 73.63% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Every existing test installs a mock IntersectionObserver in beforeEach, so
the eager-render fallback for browsers without IntersectionObserver support
was never exercised.
@bito-code-review

bito-code-review Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #3ddc9e

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: bc3c529..b58f4bb
    • superset-frontend/packages/superset-ui-core/src/chart/components/Matrixify/MatrixifyGridCell.test.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sadpandajoe
sadpandajoe requested a review from msyavuz August 11, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dashboard:performance Related to Dashboard performance packages size/L viz:charts Namespace | Anything related to viz types

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant