NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #1757 most downloaded on npm
Declarative routing for React web applications
Last release 19 days ago
15 Sep 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
1063 releases · first in 2016
Co-authored-by: Remix Run Bot hello@remix.run
Co-authored-by: Remix Run Bot hello@remix.run
See the changelog for release notes: https://github.com/remix-run/react-router/blob/v6/CHANGELOG.md#v6306
Date: 2026-08-18
@remix-run/router - Fix double slash normalization for useNavigate colon urls (3ed85d5)
navigate() is only intended for navigations within the React Router application and not for external navigations to other domainsnavigate for external navigationsFull Changelog: v6.30.5...v6.30.6
One column per quarter.
⚠️ Don't use version 6.30.5, the publish wasn't complete and the updated @remix-run/router package didn't get published properly. Use 6.30.6.
Date: 2026-08-18
⚠️ Don't use version 6.30.5, the publish wasn't complete and the updated @remix-run/router package didn't get published properly. Use 6.30.6.
react-router - Fix double slash normalization for useNavigate colon urls (#15410)
navigate() is only intended for navigations within the React Router application and not for external navigations to other domainsnavigate for external navigationsFull Changelog: v6.30.4...v6.30.5
@remix-run/router - Lift decodePath call out of hot path during route matching
Date: 2026-05-29
@remix-run/router - Lift decodePath call out of hot path during route matching (#15119)@remix-run/router - Normalize double slashes in redirect paths (#15118)Full Changelog: v6.30.3...v6.30.4
This release addresses 1 security vulnerability:
Date: 2026-01-07
This release addresses 1 security vulnerability:
Full Changelog: v6.30.2...v6.30.3
Nothing published for this version
Normalize double-slashes in resolvePath
Date: 2025-11-13
resolvePath (#14537)Full Changelog: v6.30.1...v6.30.2
Nothing published for this version
Partially revert optimization added in 6.29.0 to reduce calls to matchRoutes because it surfaced other issues
Date: 2025-05-20
6.29.0 to reduce calls to matchRoutes because it surfaced other issues (#13623)v7_relativeSplatPath is set to false (#13502)Full Changelog: v6.30.0...v6.30.1
Add fetcherKey as a parameter to patchRoutesOnNavigation
Date: 2025-02-27
fetcherKey as a parameter to patchRoutesOnNavigation (#13109)6.29.0 via #12169 that caused issues navigating to hash routes inside splat routes for applications using Lazy Route Discovery (patchRoutesOnNavigation) (#13108)Full Changelog: v6.29.0...v6.30.0
Nothing published for this version
Do not log v7 deprecation warnings in production builds
Date: 2025-01-30
signal as a parameter to patchRoutesOnNavigation (#12900)
data() result (#12845)matchRoutes calls when possible (#12169)patchRoutesOnNavigation path param for fetcher calls (#12899)Full Changelog: v6.28.2...v6.29.0
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fix manual fetcher key usage when not opted into future.v7_fetcherPersist
Date: 2025-01-16
key usage when not opted into future.v7_fetcherPersist (#12674)Full Changelog: v6.28.1...v6.28.2
Nothing published for this version
Allow users to opt out of v7 deprecation warnings by setting flags to false
Date: 2024-12-20
false (#12441)Full Changelog: v6.28.0...v6.28.1
Nothing published for this version
In preparation for v7 we've added deprecation warnings for any future flags that you have not yet opted into. Please use the flags to better prepare f…
Date: 2024-11-06
json/defer in favor of returning raw objects
Full Changelog: v6.27.0...v6.28.0
Nothing published for this version
⚠️ This may be a breaking change if you were relying on this behavior in the unstable_ API
Date: 2024-10-11
This release stabilizes a handful of "unstable" APIs in preparation for the pending React Router v7 release (see these posts for more info):
unstable_dataStrategy → dataStrategy (createBrowserRouter and friends) (Docs)unstable_patchRoutesOnNavigation → patchRoutesOnNavigation (createBrowserRouter and friends) (Docs)unstable_flushSync → flushSync (useSubmit, fetcher.load, fetcher.submit) (Docs)unstable_viewTransition → viewTransition (<Link>, <Form>, useNavigate, useSubmit) (Docs)unstable_flushSync option for navigations and fetchers (#11989)unstable_viewTransition option for navigations and the corresponding unstable_useViewTransitionState hook (#11989)unstable_dataStrategy (#11974)unstable_patchRoutesOnNavigation (#11973)
PatchRoutesOnNavigationFunctionArgs type for convenience (#11967)?index param already exists from a prior submission (#12003)useFormAction bug - when removing ?index param it would not keep other non-Remix index params (#12003)preventScrollReset through redirects during concurrent fetches (#11999)console.error on fetcher abort due to back-to-back revalidation calls (#12050)partialHydration when hydrating with errors (#12070)patchRoutesOnNavigation calls (#12055)
unstable_ APIpatchRoutesOnNavigation internally so that multiple navigations with the same start/end would only execute the function once and use the same promisepatch short circuiting if a navigation was interrupted (and the request.signal aborted) since the first invocation's patch would no-opimport() for async routes will already be cached automatically - and if not it's easy enough for users to implement this cache in userlanddiscoveredRoutes FIFO queue from unstable_patchRoutesOnNavigation (#11977)
unstable_ APIpatchRoutesOnNavigationRouteObject within PatchRoutesOnNavigationFunction's patch method so it doesn't expect agnostic route objects passed to patch (#11967)patchRoutesOnNavigation directly to useRouteError instead of wrapping them in a 400 ErrorResponse instance (#12111)Full Changelog: v6.26.2...v6.27.0
Nothing published for this version
Nothing published for this version
⚠️ If you have already adopted unstable_dataStrategy, please review carefully as this includes breaking changes to this API
Date: 2024-09-09
unstable_dataStrategy API to allow for more advanced implementations (#11943)
unstable_dataStrategy, please review carefully as this includes breaking changes to this APIunstable_HandlerResult to unstable_DataStrategyResultunstable_dataStrategy from a parallel array of unstable_DataStrategyResult[] (parallel to matches) to a key/value object of routeId => unstable_DataStrategyResult
match.shouldLoad)handlerOverride instead of returning a DataStrategyResult
handlerOverride will be wrapped up into a DataStrategyResult and returned fromm match.resolvematch.resolve() into a final results object you should not need to think about the DataStrategyResult typehandlerOverride, then you will need to assign a DataStrategyResult as the value so React Router knows if it's a successful execution or an error (see examples in the documentation for details)fetcherKey parameter to unstable_dataStrategy to allow differentiation from navigational and fetcher callsblocker.proceed is called quickly/synchronously (#11930)Full Changelog: v6.26.1...v6.26.2
Nothing published for this version
Rename unstable_patchRoutesOnMiss to unstable_patchRoutesOnNavigation to match new behavior
Date: 2024-08-15
unstable_patchRoutesOnMiss to unstable_patchRoutesOnNavigation to match new behavior (#11888)unstable_patchRoutesOnNavigation logic so that we call the method when we match routes with dynamic param or splat segments in case there exists a higher-scoring static route that we've not yet discovered (#11883)
unstable_patchRoutesOnNavigation against so that we don't re-call on subsequent navigations to the same pathFull Changelog: v6.26.0...v6.26.1
Nothing published for this version
Add a new replace(url, init?) alternative to redirect(url, init?) that performs a history.replaceState instead of a history.pushState on client-side n
Date: 2024-08-01
replace(url, init?) alternative to redirect(url, init?) that performs a history.replaceState instead of a history.pushState on client-side navigation redirects (#11811)unstable_data() API for usage with Remix Single Fetch (#11836)
createStaticHandler.query() to allow loaders/actions to return arbitrary data along with custom status/headers without forcing the serialization of data into a Response instanceunstable_dataStrategy such as serializing via turbo-stream in Remix Single Fetchstatus field from HandlerResult
status from unstable_dataStrategy you should instead do so via unstable_data()future.v7_partialHydration along with unstable_patchRoutesOnMiss (#11838)
router.state.matches will now include any partial matches so that we can render ancestor HydrateFallback componentsFull Changelog: v6.25.1...v6.26.0
Nothing published for this version
Nothing published for this version
Memoize some RouterProvider internals to reduce unnecessary re-renders
Date: 2024-07-17
RouterProvider internals to reduce unnecessary re-renders (#11803)Full Changelog: v6.25.0...v6.25.1
Nothing published for this version
This release stabilizes the future.unstable_skipActionErrorRevalidation flag into `future.v7_skipActionErrorRevalidation` in preparation for the upcom
Date: 2024-07-16
v7_skipActionErrorRevalidationThis release stabilizes the future.unstable_skipActionErrorRevalidation flag into future.v7_skipActionErrorRevalidation in preparation for the upcoming React Router v7 release.
4xx/5xx Response will not trigger a revalidation by defaultshouldRevalidate's unstable_actionStatus parameter to actionStatusfuture.unstable_skipActionErrorRevalidation as future.v7_skipActionErrorRevalidation (#11769)useMatch so matches/params reflect decoded params (#11789)unstable_patchRoutesOnMiss (#11786)unstable_patchRoutesOnMiss that matched a splat route on the server (#11790)Full Changelog: v6.24.1...v6.25.0
Nothing published for this version
Remove polyfill.io reference from warning message because the domain was sold and has since been determined to serve malware
Date: 2024-07-03
polyfill.io reference from warning message because the domain was sold and has since been determined to serve malware (#11741)
NavLinkRenderProps type for easier typing of custom NavLink callback (#11553)future.v7_relativeSplatPath, properly resolve relative paths in splat routes that are children of pathless routes (#11633)router.routes identity/reflow during route patching (#11740)Full Changelog: v6.24.0...v6.24.1
Nothing published for this version
We're really excited to release our new API for "Lazy Route Discovery" in v6.24.0! For some background information, please check out the original RFC.
Date: 2024-06-24
We're really excited to release our new API for "Lazy Route Discovery" in v6.24.0! For some background information, please check out the original RFC. The tl;dr; is that ever since we introduced the Data APIs in v6.4 via <RouterProvider>, we've been a little bummed that one of the tradeoffs was the lack of a compelling code-splitting story mirroring what we had in the <BrowserRouter>/<Routes> apps. We took a baby-step towards improving that story with route.lazy in v6.9.0, but with v6.24.0 we've gone the rest of the way.
With "Fog of War", you can now load portions of the route tree lazily via the new unstable_patchRoutesOnMiss option passed to createBrowserRouter (and it's memory/hash counterparts). This gives you a way to hook into spots where React Router is unable to match a given path and patch new routes into the route tree during the navigation (or fetcher call).
Here's a very small example, but please refer to the documentation for more information and use cases:
const router = createBrowserRouter(
[
{
id: "root",
path: "/",
Component: RootComponent,
},
],
{
async unstable_patchRoutesOnMiss({ path, patch }) {
if (path === "/a") {
// Load the `a` route (`{ path: 'a', Component: A }`)
let route = await getARoute();
// Patch the `a` route in as a new child of the `root` route
patch("root", [route]);
}
},
}
);
fetcher.submit types - remove incorrect navigate/fetcherKey/unstable_viewTransition options because they are only relevant for useSubmit (#11631)location.state values passed to <StaticRouter> (#11495)Full Changelog: v6.23.1...v6.24.0
Nothing published for this version
Allow undefined to be resolved through
Date: 2024-05-10
undefined to be resolved through <Await> (#11513)document check when checking for document.startViewTransition availability (#11544)react-router-dom/server import back to react-router-dom instead of index.ts (#11514)@remix-run/router - Support unstable_dataStrategy on staticHandler.queryRoute (#11515)Full Changelog: v6.23.0...v6.23.1
Nothing published for this version
Nothing published for this version
The new unstable_dataStrategy API is a low-level API designed for advanced use-cases where you need to take control over the data strategy for your lo
Date: 2024-04-23
The new unstable_dataStrategy API is a low-level API designed for advanced use-cases where you need to take control over the data strategy for your loader/action functions. The default implementation is today's behavior, to fetch all loaders in parallel, but this option allows users to implement more advanced data flows including Remix "Single Fetch", user-land middleware/context APIs, automatic loader caching, and more. Please see the docs for more information.
Note: This is a low-level API intended for advanced use-cases. This overrides React Router's internal handling of loader/action execution, and if done incorrectly will break your app code. Please use with caution and perform the appropriate testing.
Currently, all active loader's revalidate after any action submission, regardless of the action result. However, in the majority of cases a 4xx/5xx response from an action means that no data was actually changed and the revalidation is unnecessary. We've introduced a new future.unstable_skipActionErrorRevalidation flag that changes the behavior here, and we plan to make this the default in future version of React Router.
With this flag enabled, action's that return/throw a 4xx/5xx response status will no longer automatically revalidate. If you need to revalidate after a 4xx/5xx result with this flag enabled, you can still do that via returning true from shouldRevalidate - which now also receives a new unstable_actionStatus argument alongside actionResult so you can make decision based on the status of the action response without having to encode it into the action data.
unstable_dataStrategy configuration option (#11098, #11377)@remix-run/router - Add a new future.unstable_skipActionRevalidation future flag (#11098)@remix-run/router - SSR: Added a new skipLoaderErrorBubbling options to the staticHandler.query method to disable error bubbling by the static handler for use in Remix's Single Fetch implementation (#11098, (#11377))Full Changelog: v6.22.3...v6.23.0
Nothing published for this version
Nothing published for this version
Fix a future.v7_partialHydration bug that would re-run loaders below the boundary on hydration if SSR loader errors bubbled to a parent boundary
Date: 2024-03-07
future.v7_partialHydration bug that would re-run loaders below the boundary on hydration if SSR loader errors bubbled to a parent boundary (#11324)future.v7_partialHydration bug that would consider the router uninitialized if a route did not have a loader (#11325)Full Changelog: v6.22.2...v6.22.3
Nothing published for this version
Preserve hydrated errors during partial hydration runs
Date: 2024-02-28
Full Changelog: v6.22.1...v6.22.2
Nothing published for this version
Fix encoding/decoding issues with pre-encoded dynamic parameter values
Date: 2024-02-16
Full Changelog: v6.22.0...v6.22.1
Nothing published for this version
In 2021, the HTTP Archive launched the Core Web Vitals Technology Report dashboard:
Date: 2024-02-01
In 2021, the HTTP Archive launched the Core Web Vitals Technology Report dashboard:
By combining the powers of real-user experiences in the Chrome UX Report 26 (CrUX) dataset with web technology detections in HTTP Archive 30, we can get a glimpse into how architectural decisions like choices of CMS platform or JavaScript framework play a role in sites’ CWV performance.
They use a tool called wappalyzer to identify what technologies a given website is using by looking for certain scripts, global JS variables, or other identifying characteristics. For example, for Remix applications, they look for the global __remixContext variable to identify that a website is using Remix.
It was brought to our attention that React Router was unable to be reliably identified because there are no identifying global aspects. They are currently looking for external scripts with react-router in the name. This will identify sites using React Router from a CDN such as unpkg - but it will miss the vast majority of sites that are installing React Router from the npm registry and bundling it into their JS files. This results in drastically under-reporting the usage of React Router on the web.
Starting with version 6.22.0, sites using react-router-dom will begin adding a window.__reactRouterVersion variable that will be set to a string value of the SemVer major version number (i.e., window.__reactRouterVersion = "6";) so that they can be properly identified.
window.__reactRouterVersion for CWV Report detection (#11222)createStaticHandler future.v7_throwAbortReason flag to throw request.signal.reason (defaults to a DOMException) when a request is aborted instead of an Error such as new Error("query() call aborted: GET /path") (#11104)
DOMException was added in Node v17 so you will not get a DOMException on Node 16 and below.ErrorResponse status code if passed to getStaticContextFormError (#11213)Full Changelog: v6.21.3...v6.22.0
Nothing published for this version
Fix NavLink isPending when a basename is used
Date: 2024-01-18
NavLink isPending when a basename is used (#11195)unstable_ prefix from Blocker/BlockerFunction types (#11187)Full Changelog: v6.21.2...v6.21.3
Nothing published for this version
Leverage useId for internal fetcher keys when available
Date: 2024-01-11
useId for internal fetcher keys when available (#11166)Full Changelog: v6.21.1...v6.21.2
Nothing published for this version
Fix bug with route.lazy not working correctly on initial SPA load when v7_partialHydration is specified
Date: 2023-12-21
route.lazy not working correctly on initial SPA load when v7_partialHydration is specified (#11121)submitting phase (#11102)resolveTo (#11097)Full Changelog: v6.21.0...v6.21.1
Nothing published for this version
We fixed a splat route path-resolution bug in 6.19.0, but later determined a large number of applications were relying on the buggy behavior, so we re
Date: 2023-12-13
future.v7_relativeSplatPathWe fixed a splat route path-resolution bug in 6.19.0, but later determined a large number of applications were relying on the buggy behavior, so we reverted the fix in 6.20.1 (see #10983, #11052, #11078).
The buggy behavior is that the default behavior when resolving relative paths inside a splat route would ignore any splat (*) portion of the current route path. When the future flag is enabled, splat portions are included in relative path logic within splat routes.
For more information, please refer to the useResolvedPath docs and/or the detailed changelog entry.
We added a new future.v7_partialHydration future flag for the @remix-run/router that enables partial hydration of a data router when Server-Side Rendering. This allows you to provide hydrationData.loaderData that has values for some initially matched route loaders, but not all. When this flag is enabled, the router will call loader functions for routes that do not have hydration loader data during router.initialize(), and it will render down to the deepest provided HydrateFallback (up to the first route without hydration data) while it executes the unhydrated routes. (#11033)
future.v7_relativeSplatPath flag to implement a breaking bug fix to relative routing when inside a splat route. (#11087)future.v7_partialHydration future flag that enables partial hydration of a data router when Server-Side Rendering (#11033)ErrorBoundary's (#11071)loader/action functions (#11061)relative="path" issue when rendering Link/NavLink outside of matched routes (#11062)Full Changelog: v6.20.1...v6.21.0
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →