fix: dedupe react/react-dom in Vite to stop duplicate-copy hook crash#121
Merged
Conversation
portos-ai-toolkit declares react/react-dom@^18 as optional peers, so npm hoists react@18 to the root node_modules while the app uses react@19 under client/node_modules. Hoisted packages such as react-router-dom then resolve the root react@18, loading two copies of React in the browser and crashing with 'Invalid hook call' / useRef on null (blank page). resolve.dedupe forces every bare react/react-dom import to the single client copy.
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.
Problem
After a fresh
pm2 start, the web UI rendered a blank white page with:This is the classic two copies of React symptom.
Root cause
portos-ai-toolkit(added with the shared-CDP-browser change) declaresreact/react-dom@^18.3.1as optional peers. npm auto-installed them and hoistedreact@18+react-dom@18to the rootnode_modules/, where hoisted packages (react-router-dom,react-hot-toast,zustand, etc.) deduped onto React 18 — while the app itself loads React 19 fromclient/node_modules/. When the hoistedreact-router-dom'sBrowserRoutercalleduseRef, it got the wrong/null React and crashed.npm
overridescan't fix this cleanly: it refuses to override the optional-peer-induced copies.Fix
Add
resolve.dedupe: ['react', 'react-dom']toclient/vite.config.ts, forcing every barereact/react-domimport (including from hoisted packages) to resolve to the single React 19 copy at the client root. This is the documented Vite remedy for "more than one copy of React".Verification
http://localhost:6373in a browser: 0 console errors (was the React hook crash); page renders.react-leaflet@5requires react@19 — dedupe to the client copy satisfies it.schedulerfollowsreact-domresolution and needs no entry.