Skip to content

Upgrade React Router to v8#153

Open
sneridagh wants to merge 3 commits into
mainfrom
upgrade-react-router-v8
Open

Upgrade React Router to v8#153
sneridagh wants to merge 3 commits into
mainfrom
upgrade-react-router-v8

Conversation

@sneridagh

@sneridagh sneridagh commented Jul 19, 2026

Copy link
Copy Markdown
Member

Summary

Upgrades React Router from 7.14.0 to 8.2.0 (react-router, @react-router/dev, @react-router/node, @react-router/serve), and remix-i18next from 7.1.0 to 8.0.0 (required, since remix-i18next only supports React Router v8 starting at its own v8).

React Router v8's breaking changes are mostly the codification of flags that were already opt-in in v7 (future.v8_middleware, which this app had already adopted), plus a couple of renamed fields. The bulk of this PR is migrating off remix-i18next v7's RemixI18Next class, which was removed in v8 in favor of a middleware-based API.

React Router v8 changes

  • unstable_pattern / unstable_urlpattern / url: renamed (now stable, unprefixed) across loader/action test helpers in apps/aurora, packages/cmsui, and packages/contents.
  • MetaMatch.dataMetaMatch.loaderData: updated meta() functions in cmsui, contents, and publicui root layouts/routes that read the root route's loader data from matches.
  • Removed the now-default future.v8_middleware flag from apps/aurora/react-router.config.ts.
  • Bumped apps/aurora engines to Node >=22.22.0 (v8's minimum).

remix-i18next v8 migration

  • Rewrote apps/aurora/app/i18next.server.ts to use createI18nextMiddleware, replacing the removed RemixI18Next class and its /server, /client, /react subpath exports. It now exports [i18nextMiddleware, getLocale, getInstance].
  • Registered i18nextMiddleware in root.tsx's middleware array so getLocale(context) / getInstance(context) work from route context, and updated the cmsui, contents, and publicui root layouts that independently called i18next.getLocale(request) to use the new context-based getLocale.
  • Simplified entry.server.tsx to render with the middleware-provided instance (getInstance(loadContext)) instead of manually creating and initializing a per-request i18next instance.
  • Replaced the removed useChangeLanguage hook in root.tsx's Layout with an equivalent useTranslation + useEffect sync.
  • Important fix: defaultNS and ns are independent i18next options. The removed getInitialNamespaces()/getRouteNamespaces() helpers previously supplied an explicit ns array computed from matched routes. Simply dropping them (relying on defaultNS: 'common' alone) would silently make i18next preload the wrong translation namespace instead of common, since ns defaults independently to ['translation']. Fixed by explicitly setting ns: i18n.defaultNS in both the client (entry.client.tsx) and server (i18next.server.ts) init options.

Dependency note: prettier bump (3.6.2 → 3.9.5)

@react-router/dev@8.2.0 has a hard dependency on prettier: ^3.8.3, which the repo's previously-resolved prettier@3.6.2 (satisfying packages/tooling's ^3.5.2 range) can no longer share a single resolved version with. pnpm's natural resolution bumps the shared prettier install to 3.9.5 to satisfy both ranges. This is a required consequence of the upgrade, not incidental drift — earlier revisions of this PR mistakenly tried to pin it back down; that's been reverted. Note that prettier 3.9.5 has some formatting-rule differences from 3.6.2, so running prettier --write repo-wide after this merges may produce unrelated formatting diffs on files untouched by this PR; that's expected and best handled as its own follow-up formatting pass rather than bundled here.

Test plan

  • pnpm installremix-i18next peer warning against react-router is gone
  • Typecheck clean across apps/aurora, packages/cmsui, packages/publicui, packages/layout, packages/react-router (packages/contents has pre-existing, unrelated type errors not touched by this change)
  • Full test suites pass: apps/aurora (44/44), packages/cmsui (178/178), packages/contents (3/3), packages/layout (8/8), packages/react-router (5/5)
  • Production build succeeds (pnpm build)
  • Smoke-tested pnpm start:prod boot: middleware chain, routing, and SSR run end-to-end (the resulting 500 is expected — no local Plone backend was running in the test environment; it renders via the app's own ErrorBoundary, confirming the request pipeline completed)
  • prettier/eslint clean on all changed files

Bumps react-router, @react-router/dev, @react-router/node, and
@react-router/serve to 8.2.0, and remix-i18next to 8.0.0 (required,
since it only supports React Router v8 starting at its own v8).

- Migrate i18next.server.ts to remix-i18next's v8 middleware API
  (createI18nextMiddleware), replacing the removed RemixI18Next class
  and its /server, /client, /react subpath exports.
- Register the i18next middleware in root.tsx so getLocale/getInstance
  work from route context; replace useChangeLanguage with a
  useTranslation + useEffect sync.
- Fix explicit ns handling in the client and server i18next config:
  defaultNS and ns are independent i18next options, so dropping the
  namespace helpers without setting ns explicitly would have made the
  app preload the wrong ("translation") namespace instead of "common".
- Rename unstable_pattern/unstable_url to pattern/url across loader and
  action test helpers (now stable, unprefixed fields in v8).
- Update meta() functions in cmsui, contents, and publicui routes to
  read match.loaderData instead of the removed match.data.
- Remove the now-default v8_middleware future flag.
- Bump apps/aurora engines to Node >=22.22.0.
@sneridagh
sneridagh requested a review from pnicolli July 19, 2026 18:51
Running pnpm install for the React Router upgrade had re-resolved
prettier's unpinned devDependency range (packages/tooling: ^3.5.2)
from 3.6.2 to 3.9.5, an unrelated side effect that would have caused
prettier to reformat unrelated files across the repo. Restored the
3.6.2 resolution (matching main) without adding an override, so this
PR stays scoped to the React Router upgrade.
The previous commit treated the prettier 3.6.2 -> 3.9.5 resolution
bump as an unrelated side effect and pinned it back down. That was
wrong: @react-router/dev@8.2.0 has a hard dependency on
`prettier: ^3.8.3`, which packages/tooling's existing ^3.5.2 range
(previously satisfied by 3.6.2) can no longer share a single resolved
version with. pnpm's natural resolution of 3.9.5 (satisfying both
ranges) is correct and necessary for this upgrade, not incidental
drift to suppress.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant