Skip to content

TODO: Adopt React 18 concurrent features now that the upgrade has landed #39890

@rusackas

Description

@rusackas

Now that #38563 has landed React 18, none of the concurrent-rendering APIs are actually being used yet. This is a tracking issue for adopting the features that move the needle on Superset's perceived performance and forward-compat.

Priorities are ordered roughly by ROI / dependency order — earlier items unblock or de-risk later ones.

Foundation

Concurrent-rendering wins

  • Replace useDebounceValue with useDeferredValue in inputs that filter large client-side lists. useDeferredValue is strictly better than a fixed-delay debounce: deferred updates get interrupted on each keystroke and run at low priority. Targets:
    • SqlLab/components/TableExploreTree/index.tsx:317 (PR perf(sql-lab): debounce schema browser search #39489 introduced the debounce — this is the natural follow-up)
    • explore/components/DatasourcePanel/index.tsx:163 (column search)
    • packages/superset-ui-core/src/components/Select/Select.tsx:387 (used app-wide)
    • explore/components/controls/TextControl/index.tsx:90
    • filters/components/Select/SelectFilterPlugin.tsx:265
    • dashboard/components/nativeFilters/FilterBar/index.tsx:97 (publishDataMask)
  • Wrap heavy cascading Redux dispatches in startTransition so the input that triggered them stays responsive. Highest-impact site: native filter application (changing a filter today blocks the input on chart re-renders). Pair with useTransition's isPending to drive a subtle "applying…" indicator on affected chart cards. Blocked by Migrate to react-redux v8 with a typed AppDispatch / useAppDispatch #39927 — needs typed dispatch + tearing-free store reads.
    • dashboard/components/nativeFilters/FilterBar/index.tsx:268 (updateDataMask)
    • dashboard/components/nativeFilters/FilterBar/index.tsx:455 (saveChartCustomization)
    • explore/components/ExploreViewContainer/index.tsx:468 (triggerQuery after control change)
    • SqlLab/components/TabbedSqlEditors/index.tsx:145 (tab switch)

Lower-priority / opportunistic

  • useId audit — most nanoid usage in the codebase is for persistent data keys (correct, leave alone). The few real DOM-id sites (e.g. DateFilterLabel.tsx:374-375) could move to useId for hygiene but aren't urgent.
  • Suspense coverage — already ~95% on lazy boundaries. Skip unless a specific gap appears.

Notes / risks

  • StrictMode rollout: turning it on may surface failures in component tests that assume effects run exactly once. Plan for a cleanup pass; don't merge alongside other work.
  • Selector hygiene under concurrent rendering: selectors returning a new object reference per call (useSelector(state => ({a, b}))) become a tearing risk. Worth a sweep alongside the react-redux v8 bump (tracked in Migrate to react-redux v8 with a typed AppDispatch / useAppDispatch #39927).
  • Measurement: profile each concurrent-feature PR with React DevTools Profiler before/after. The wins are perceptual; numbers help defend the change.

Suggested PR sequencing

  1. StrictMode + the resulting effect fixes — done in feat(frontend): enable React StrictMode at root #39893
  2. useDeferredValue migration (SQL Lab tree first, core Select after) — does not require v8
  3. react-redux v8 typed-dispatch migration — see Migrate to react-redux v8 with a typed AppDispatch / useAppDispatch #39927
  4. startTransition around native filter apply, with isPending indicator — depends on (3)

PRs should reference this issue.

Metadata

Metadata

Labels

frontend:refactorRelated to refactoring the frontend

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions