Migrating from React Router v6
React Router v7 is a major version upgrade from v6, but the migration path is designed to be incremental. This guide walks you through the process of upgrading your React Router v6 application to v7.Prerequisites
React Router v7 requires the following minimum versions:- Node.js: v20 or higher
- React: v18 or higher
- react-dom: v18 or higher
Migration Strategy
The recommended approach is to adopt all future flags in v6 before upgrading to v7. This allows you to update your app one change at a time, committing and shipping each change incrementally.Step 1: Update to Latest v6.x
First, update to the latest minor version of React Router v6 to access all future flags:Step 2: Enable Future Flags
Enable each future flag one at a time, test your application, and commit the changes. This incremental approach reduces risk.v7_relativeSplatPath
What it changes: Updates relative path matching and linking for multi-segment splat paths likedashboard/*.
Enable the flag:
<Route path="dashboard/*">, split them into parent and child routes:
.. segment:
v7_startTransition
What it changes: UsesReact.useTransition instead of React.useState for router state updates.
Enable the flag:
React.lazy calls from inside components to the module scope. React.lazy inside components is incompatible with React.useTransition.
v7_fetcherPersist
Applies to:createBrowserRouter only
What it changes: The fetcher lifecycle is now based on when it returns to idle state rather than when its owner component unmounts.
Enable the flag:
useFetchers - fetchers may persist longer than before. Adjust rendering logic if needed.
v7_normalizeFormMethod
Applies to:createBrowserRouter only
What it changes: Normalizes formMethod fields as uppercase HTTP methods.
Enable the flag:
formMethod to UPPERCASE values:
v7_partialHydration
Applies to:createBrowserRouter only
What it changes: Enables partial hydration for SSR applications.
Enable the flag:
fallbackElement with HydrateFallback on your routes:
v7_skipActionErrorRevalidation
Applies to:createBrowserRouter only
What it changes: Loaders no longer revalidate by default when an action returns a 4xx/5xx status.
Enable the flag:
shouldRevalidate:
Step 3: Update Deprecated APIs
Replacejson and defer with raw objects:
Response.json():
Step 4: Upgrade to v7
Once all future flags are enabled and your app works correctly, upgrade to v7:react-router is needed in your package.json for v7.
Step 5: Update Imports
Change all imports fromreact-router-dom to react-router:
Step 6: Update DOM-Specific Imports
RouterProvider and HydratedRouter now come from a deep import:
Breaking Changes Summary
Package Consolidation
- All packages collapsed into
react-router react-router-domis maintained for compatibility but re-exports fromreact-router- Runtime-specific exports moved to
@react-router/node,@react-router/cloudflare, etc.
Removed APIs
defer(use raw promises)json(use raw objects orResponse.json())AbortedDeferredErrorTypedDeferredDataUNSAFE_DeferredData- Future flags (now default behavior):
v7_startTransitionv7_relativeSplatPathv7_fetcherPersistv7_normalizeFormMethodv7_partialHydrationv7_skipActionErrorRevalidation
Type Changes
useFetchergeneric now expects the function type (e.g.,typeof loader) instead of the data type- Update usage:
useFetcher<typeof loader>()instead ofuseFetcher<LoaderData>()
Minimum Version Requirements
- Node.js: v16 → v20
- React: Minimum v18 (no change)
Common Issues
Relative Links in Splat Routes
If links break after enablingv7_relativeSplatPath, ensure you’ve split multi-segment splat routes and updated relative paths with ../.
Fetcher Lifecycle Changes
Withv7_fetcherPersist, fetchers remain in the router state until idle. If you see stale fetchers in useFetchers(), this is expected behavior.
Form Method Casing
After enablingv7_normalizeFormMethod, all formMethod checks must use uppercase: POST, GET, PUT, DELETE, PATCH.
Next Steps
After completing this migration, consider:- Framework Mode: If you want SSR, type safety, and routing conventions, explore React Router Framework Mode
- Type Safety: Learn about automatic type generation for route modules
- Prerendering: Set up static site generation for better performance