chore(sample-apps): upgrade react-router from v6 to v8 - #2358
Conversation
Replaces react-router-dom@6 with react-router@7 in the zoom-clone, livestream-app, audio-rooms and messenger-clone React sample apps. - react-router-dom is no longer needed in v7; imports now come from react-router, with RouterProvider from react-router/dom - no future-flag migrations were required: none of the apps use multi-segment splat routes, React.lazy in component scope, fetchers, formMethod comparisons, fallbackElement or the deprecated json()/defer() helpers
Prepares for react-router v8, which peers on react >=19.2.7. Every non-RN workspace moves from 19.2.3 to 19.2.8 so that a workspace-linked package and its consumer always agree on the react version - otherwise an app and the video SDK load two separate react instances and every SDK component using hooks throws "Invalid hook call". React Native stays on 19.2.3: react-native@0.86.2 peers on ^19.2.3 and the RN packages and apps now get their own nested copy. The root react/react-dom devDependencies are not imported by the root workspace - they exist to pin which copy yarn hoists. Yarn hoists a single react version chosen by dependent count across the whole graph, and the RN ecosystem outweighs the web side, so without this entry 19.2.3 stays at the root and every web workspace gets a nested 19.2.8 duplicate. A resolutions entry would also pin it but would force RN off 19.2.3 too.
Bumps react-router from 7.18.2 to 8.3.0 in the zoom-clone, livestream-app, audio-rooms and messenger-clone React sample apps. No route code changes were needed: none of the apps read match.data or define meta functions, so there is no data -> loaderData migration, and no loader uses the context argument that future.v8_middleware changes. The remaining v8 flags are framework-mode only, and react-router-dom was already dropped during the v7 upgrade.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughThe pull request upgrades React and React DOM to 19.2.8, migrates four React sample apps from ChangesReact dependency and router migration
React Native Jest configuration
Repository ignore rule
Estimated code review effort: 2 (Simple) | ~15 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… root pin Pinning react at the root moved react-native, react-native-gesture-handler and babel-preset-expo out of the root node_modules into per-workspace copies, which broke three things that silently relied on them being hoisted: - preset: 'react-native' is a shim that requires @react-native/jest-preset, which was never a declared dependency. It is now declared and referenced directly. - setupFilesAfterEnv pointed at a hardcoded <rootDir>/../../node_modules path for the gesture-handler jest setup; it now uses require.resolve. - expo-module-scripts/babel.config.base.cjs resolves babel-preset-expo via a relative sibling path, so babel-preset-expo is pinned at the root to keep it next to expo-module-scripts. The jest moduleNameMapper is the one addition that is not a hoisting artifact: video-react-bindings is shared by web and React Native, so its single copy resolves one react version. With the root on 19.2.8 the RN tests would otherwise load bindings' 19.2.8 alongside this package's 19.2.3 and fail with "more than one copy of React".
Brings in the dependency-range alignment from #2359, which fixes the 20 @typescript-eslint no-shadow errors that were failing lint on main and therefore on this branch. Conflicts were all in manifests this branch also touches. Resolved by taking main's aligned ranges wholesale and re-applying only this branch's deliberate overrides: - react/react-dom 19.2.8 in the non-React-Native workspaces, plus the root pins that keep 19.2.8 hoisted - react-router ^8.3.0 in the four upgraded sample apps, replacing the react-router-dom ^6.30.4 that main had bumped - babel-preset-expo pinned at the root Everything else - eslint 9.39.5, prettier 3.9.6, nx 22.7.8, @types/react ~19.2.18 and the rest of the 95 aligned ranges - comes from main unchanged.
Bundle sizeBuilt package output. Sizes in KB; delta vs No significant package size increase vs |
…n tests expo-module-scripts was a single devDependency used by exactly one file, expo-config-plugin/jest.config.js, which re-exported its 12-line jest-preset-plugin. Only testEnvironment, testRegex and the babel transform were doing anything there: the plugin tests are plain node TypeScript with no snapshots and no JSX, so the jest-watch-typeahead watch plugins and the prettier@2 prettierPath were dead weight. In exchange it pulled in @babel/cli, jest-expo, eslint-config-universe, ts-jest, prettier@2 and a second @react-native/jest-preset at 0.85.3, which mismatched the 0.86.2 this package already declares directly. The preset also resolved babel-preset-expo through a relative sibling path in babel.config.base.cjs, which was the only reason babel-preset-expo was pinned at the repo root. Removing it lets that pin go too, which clears the YN0002 warning about the root not providing react-refresh, a non-optional peer dependency of babel-preset-expo. The two Expo sample apps keep their own copies via their own expo dependency. Verified: 97 plugin tests and the full react-native-sdk suite and type check pass, bob build succeeds, and the only yarn install warning that disappears is the YN0002 line.
💡 Overview
Upgrades
zoom-clone,livestream-app,audio-roomsandmessenger-clonefromreact-router-dom@6toreact-router@8, in two steps per the official guides (v6 → v7, v7 → v8).No route code changes were needed. The only source edits are import paths (
react-router-dom→react-router,RouterProviderfromreact-router/dom). None of the apps use multi-segment splat routes, fetchers,fallbackElement, actions,match.dataormeta, so no future-flag ordata→loaderDatamigration applied.📝 Implementation notes
Most of this diff is the React bump that
react-router@8forces: it peers onreact >=19.2.7and the monorepo pinned19.2.3. All non-React-Native workspaces move to19.2.8; RN stays on19.2.3(react-native@0.86.2peers on^19.2.3).Two things look odd and are load-bearing:
Important
react/react-domin the rootdevDependencies— the root doesn't import React. The entry pins which copy yarn hoists, since a root dependency must resolve from rootnode_modules. Without it yarn keeps19.2.3at the root (the RN ecosystem outweighs the web side in dependent count), every web workspace gets a nested19.2.8, and an app plus the workspace-linked SDK load two React instances — every SDK component using hooks throwsInvalid hook call.moduleNameMapperinpackages/react-native-sdk/jest.config.js—video-react-bindingsis shared by web and RN, so its single copy resolves one React version. With the root on19.2.8the RN tests would load bindings'19.2.8next to that package's19.2.3and fail withmore than one copy of React. While the two platforms sit on different versions, one side needs an override; this keeps it in test-only config.Pinning React at the root also de-hoisted
react-native,react-native-gesture-handlerandbabel-preset-expo, breaking three things in the RN SDK test setup that assumed root hoisting: thereact-nativejest preset shim (now@react-native/jest-preset, declared explicitly), a hardcoded<rootDir>/../../node_modulespath (nowrequire.resolve), andexpo-module-scripts' relative sibling lookup ofbabel-preset-expo(third-party, so that package is pinned at the root).Merged
mainfor #2359. Note it had bumpedreact-router-domto^6.30.4in these apps; conflicts are resolved toreact-router ^8.3.0, andreact-router-domis gone from every manifest and the lockfile.✅ Verification
lint:ci:all(0 errors) ·test:ci:all(844 passed) ·test:react-native:sdk(124 tests) ·NODE_ENV=production build:all·install --immutable.Every route and nav primitive exercised per app in a browser, with real calls joined against the demo backend.
react-dogfoodchecked. React Nativedogfoodrebuilt and re-run on a physical iPhone, since the hoisting change affects RN resolution.zoom-clone's/call/<unknown>dead-ends on an empty outlet — its*child renders<Navigate to="/">, whose loader redirects to/call/lobbywith nocallId, matching*again. Verified identical on the v6 baseline, so not upgrade fallout.🎫 Ticket: https://linear.app/stream/issue/REACT-1053/upgrade-react-router-in-react-sample-apps-from-v6-to-v8
📑 Docs: n/a — sample apps only, no public API change
Summary by CodeRabbit
Bug Fixes
Chores