fix(web): dedupe React so hook-using deps stop crashing - #1211
Merged
Conversation
Radix Popover crashed with "Invalid hook call" because @radix-ui/react-popover is not linked into web/node_modules and resolves react from the repo root — a different instance than the one app code imports. Two React copies make every hook-using third party component throw on render and unmount the whole tree. The VitePWA dev service worker also pulls its workbox imports only after registration, so Vite re-optimizes deps and force-reloads the page mid-run, which nondeterministically kills whichever e2e test is in flight.
There was a problem hiding this comment.
Findings
No findings.
Summary
Review mode: initial
No diff-introduced issues found. Residual risk: this config-only change depends on Vite/Bun dependency resolution behavior, so coverage should come from web typecheck/test/build plus E2E on a cold Vite dependency cache.
Testing
Not run (automation).
HAPI Bot
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two Vite dev/build config additions:
resolve.dedupe: ['react', 'react-dom']optimizeDeps.includefor the four workbox packagesWhy (1): duplicate React silently breaks any hook-using dependency
@radix-ui/react-popoveris declared inweb/package.json, but it is not linked intoweb/node_modules— onlyreact-dialogandreact-slotare:So it resolves React from the repo root instead, which is a physically different copy from the one app code imports:
Two React instances make every hook-using third-party component throw
Invalid hook callon render. Without an error boundary React then unmounts the whole tree, so the symptom is a blank page rather than a visible error.Re-running
bun installdoes not change the layout, so this is not stale local state.Impact: this was already failing 20 tests on main
mainThe collected total goes up by 57 because the affected files were dying during import — their tests were never counted at all.
I found this while building a feature that renders a Radix Popover — the component white-screened the entire page. The failing tests on main turned out to be the same root cause.
Why (2): dev service worker forces a mid-run page reload
VitePWAdevOptions.enabled: trueinjects SW registration into every served page. The workbox imports insidesw.tsare only discovered after registration, so Vite re-optimizes deps and issuesoptimized dependencies changed → reloading. On a cold cache this reliably kills whichever e2e test is in flight (elements vanish mid-assertion).Declaring the four workbox packages in
optimizeDeps.includepre-bundles them at startup instead. This affects all e2e fixtures, not any one suite.Verification
npm run test— 1560/1560 pass (was 1483/1503 with 20 failures)npm run typecheck— cleannpm run build— succeeds, PWA manifest generated normallynpm run test:mermaid-lightbox:e2e— 15/15 passNote
resolve.dedupeis a safety net, not a substitute for fixing the install layout. If the real fix is to make bun link@radix-ui/react-popoverintoweb/node_modules, I'm happy to change direction — but the dedupe is worth keeping regardless, since it makes the app resilient to this class of hoisting difference.