fix(sql-lab): prevent crash when host shell lacks useAppDispatch export#40506
fix(sql-lab): prevent crash when host shell lacks useAppDispatch export#40506yousoph wants to merge 6 commits into
Conversation
In Module Federation deployments where the host shell shares src/views/store as a singleton, a version skew between the shell and the SQL Lab remote chunk can leave useAppDispatch undefined at runtime. This causes `TypeError: o.useAppDispatch is not a function` when any SQL Lab component tries to render. Root cause: commit 785a08c added useAppDispatch to store.ts and commit 6842bb3 migrated all SQL Lab components to call it. When a host shell is built against a version of store.ts that predates 785a08c, the shared store module it provides has no useAppDispatch export. SQL Lab (built from the newer code) destructures an undefined value and then immediately tries to call it. Fix: introduce a thin shim at src/SqlLab/hooks/useAppDispatch.ts that re-exports useAppDispatch with a nullish-coalesce fallback to useDispatch. All SQL Lab components now import from the shim instead of directly from src/views/store. In a correctly up-to-date deployment the shim is transparent; in a version-skewed deployment SQL Lab continues to work (with untyped dispatch) rather than crashing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Code Review Agent Run #cd61deActionable Suggestions - 0Additional Suggestions - 2
Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
There was a problem hiding this comment.
Pull request overview
This PR prevents SQL Lab from crashing in Module Federation deployments when the host shell provides an older shared src/views/store module that does not export useAppDispatch, by routing SQL Lab’s dispatch hook through a local shim that can fall back to react-redux’s useDispatch.
Changes:
- Added
src/SqlLab/hooks/useAppDispatch.tsshim that re-exportsuseAppDispatchfromsrc/views/storewith a runtime fallback touseDispatch. - Updated SQL Lab components/hooks to import
useAppDispatchfrom the shim instead ofsrc/views/store. - Kept typed dispatch (
AppDispatch) as the public hook return type for SQL Lab call sites.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| superset-frontend/src/SqlLab/hooks/useAppDispatch.ts | Introduces a guarded useAppDispatch export with a useDispatch fallback for version-skewed shared store modules. |
| superset-frontend/src/SqlLab/components/TablePreview/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/TableExploreTree/useTreeData.ts | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/TableExploreTree/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/TableElement/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/SqlEditorTopBar/useDatabaseSelector.ts | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/SqlEditorTabHeader/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/SqlEditor/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/SouthPane/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx | Splits selector/dispatch imports so useAppDispatch comes from the shim. |
| superset-frontend/src/SqlLab/components/ResultSet/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/QueryTable/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/QueryLimitSelect/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/QueryAutoRefresh/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/PopEditorTab/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/ExploreCtasResultsButton/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/EditorWrapper/useKeywords.ts | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/EditorWrapper/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
| superset-frontend/src/SqlLab/components/EditorAutoSync/index.tsx | Switches useAppDispatch import to the SQL Lab shim. |
aminghadersohi
left a comment
There was a problem hiding this comment.
The shim approach is correct and well-scoped. Root cause confirmed: commit 785a08c7d5 ("chore(frontend): export typed useAppDispatch / useAppSelector hooks") added useAppDispatch as a named constant to store.ts; any Module Federation host shell built before that commit will serve a store module object without that key, causing the TypeError on every SQL Lab load.
What's right:
??evaluated at module-init time — correct for a static version-skew condition.- Fallback to raw
useDispatchis safe at runtime: thunk middleware is still active in the store, so thunk dispatch works even without the typed wrapper. - Shim is in
src/SqlLab/rather than modifyingsrc/views/store— correct layer. Keeps the fallback isolated to the remote chunk and doesn't affect the rest of the codebase. - All 19 import sites updated consistently.
Two non-blocking suggestions:
-
Consider adding a unit test for the fallback path. The
??logic is the critical part of this fix, but it's untested. It's possible to exercise it viajest.mock('src/views/store', () => ({}))and asserting the exporteduseAppDispatchequalsuseDispatch. Without it, a future refactor that accidentally removes theas | undefinedcast could silently break the fallback. -
Minor type honesty nit: In the fallback path,
useDispatchreturnsDispatch<AnyAction>but the export types it as() => AppDispatch. Works at runtime (thunk middleware handles it), but explicitly castinguseDispatch as () => AppDispatchin the??branch would make the intentional narrowing visible rather than implicit.
Both are optional. The fix is correct as-is.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #40506 +/- ##
==========================================
+ Coverage 64.01% 64.05% +0.03%
==========================================
Files 2594 2594
Lines 139898 139681 -217
Branches 32470 32445 -25
==========================================
- Hits 89558 89470 -88
+ Misses 48795 48673 -122
+ Partials 1545 1538 -7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
aminghadersohi
left a comment
There was a problem hiding this comment.
Reviewed post-approval commit fa49f1c. It is a merge-from-master bringing in unrelated Python soft-delete features and routine dependency bumps — none of the PR's 20 TypeScript files were touched. Prior approval stands. No new concerns.
Summary
Fixes
TypeError: o.useAppDispatch is not a functionwhen clicking SQL Lab.src/SqlLab/hooks/useAppDispatch.tsthat re-exportsuseAppDispatchfromsrc/views/storewith a nullish-coalesce fallback touseDispatchRoot cause
In Module Federation deployments where the host shell shares
src/views/storeas a singleton, a version skew between the shell bundle and the SQL Lab remote chunk can leaveuseAppDispatchundefined at runtime. The shell was built beforeuseAppDispatchwas exported (commit 785a08c), but SQL Lab was built after. SQL Lab gets the older shared module and crashes.Fix
The shim is transparent in up-to-date deployments. In version-skewed deployments it falls back silently to
useDispatchrather than crashing.Test plan
TypeError: useAppDispatch is not a functioncd superset-frontend && npm run type-checkpasses🤖 Generated with Claude Code