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
Release v7.18.4
Release v7.18.4 (#15498)
See the changelog for release notes: https://github.com/remix-run/react-router/blob/v7/CHANGELOG.md#v7184
Co-authored-by: Remix Run Bot hello@remix.run
Co-authored-by: Remix Run Bot hello@remix.run
One column per quarter.
See the changelog for release notes: https://github.com/remix-run/react-router/blob/v7/CHANGELOG.md#v7183
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/v7/CHANGELOG.md#v7182
Date: 2026-07-28
react-router - Harden RSC CSRF codepaths. (#15353)Full Changelog: v7.18.1...v7.18.2
react-router-dom - Fix incorrect package.json main field for CommonJS builds
Date: 2026-06-29
react-router-dom - Fix incorrect package.json main field for CommonJS builds (#15238)Full Changelog: v7.18.0...v7.18.1
We made a bug fix in our underlying CSRF checks in this release that may be a "breaking bug fix" for some users deployed behind a reverse proxy. The C
Date: 2026-06-16
We made a bug fix in our underlying CSRF checks in this release that may be a "breaking bug fix" for some users deployed behind a reverse proxy. The CSRF check now checks directly against the host in the request url provided, instead of looking directly at HTTP headers which is an adapter concern. If your adapter is not setting the expected host in the request URL, you may need to add the new internal host to your allowedActionOrigins config. This is most likely to occur in @react-router/serve apps or @react-router/express apps without the trust proxy setting enabled. We recommend testing this against application mutation requests as part of your upgrade.
@react-router/architect - Add a useRequestContextDomainName option to createRequestHandler to derive request URL hosts from the API Gateway request context (#15185)
react-router - Fix server handler prerender responses when using ssr: false and future.v8_trailingSlashAwareDataRequests: true (#15173)
react-router - Use the ServerRouter nonce for nonce-aware SSR components when they don't provide their own value so strict CSP pages can load them (#15170)react-router - Use turbo-stream to serialize and deserialize Framework Mode hydration errors (#15175)react-router - Optimize route matching by extending precomputed route branches to include matchers (#15186)react-router - Use the constructed request URL host instead of header checks when validating action request origins in the CSRF check (#15185)react-router - Remove the un-documented custom error serialization logic from Data Mode SSR built-in hydration flows (#15175)react-router - Validate protocols in RSC render redirects (#15177)react-router - Consolidate url normalization logic and better handle mixed slashes (#15176)@react-router/dev - Pass Vite server.watch config to child compiler in development mode. (#15178)@react-router/dev - Ignore external Vite server environments in Framework Mode build hooks (#14883)
future.v8_viteEnvironmentApi is enabled, React Router previously treated any non-client Vite environment as its own server build@react-router/express - Adjust express adapter host computation (#15185)
x-forwarded-host based on trust proxy settingFull Changelog: v7.17.0...v7.18.0
react-router - Ship a subset of the official documentation inside the react-router package
Date: 2026-06-04
react-router - Ship a subset of the official documentation inside the react-router package (#15121)
node_modules/react-router/docs, letting AI coding agents and the React Router agent skills read official docs locallyapi/), community/ content, and tutorials (tutorials/)@react-router/dev - Fix future flag warning URLs and only log each future flag warning one time (#15138)⚠️ Unstable features are not recommended for production use
@react-router/dev - Prevent RSC route module server exports from being scanned by the client dependency optimizer when future.unstable_optimizeDeps is enabled. (#15005)Full Changelog: v7.16.0...v7.17.0
react-router - Stabilize future.unstable_trailingSlashAwareDataRequests as future.v8_trailingSlashAwareDataRequests
Date: 2026-05-28
react-router - Stabilize future.unstable_trailingSlashAwareDataRequests as future.v8_trailingSlashAwareDataRequests (#15098)
@react-router/dev - Stabilize future.unstable_trailingSlashAwareDataRequests as future.v8_trailingSlashAwareDataRequests (#15098)
@react-router/dev - Log future flag warnings for upcoming React Router v8 flags (#15029)
v8_middleware, v8_splitRouteModules, v8_viteEnvironmentApi, v8_passThroughRequests, v8_trailingSlashAwareDataRequestsreact-router - Disable manifest path when lazy route dicovery is disabled (#15068)
react-router - Fix browser URL creation to use the configured history window instead of the global window. (#15066)
createBrowserURLImpl so custom window contexts keep the correct URL origin.react-router - Fix useNavigation() return type to preserve discriminated union across navigation states (#15095)
react-router - Widen MetaDescriptor script:ld+json type from LdJsonObject to LdJsonObject | LdJsonObject[] to permit multiple JSON-LD schemas in a single <script type="application/ld+json"> tag emitted by <Meta /> (#15082)
react-router-dom - Remove stale/invalid unpkg field from package.json. This was removed from other packages with the release of v7 but missed in the react-router-dom re-export package (#15075)
@react-router/express - Ignore writes after Express responses close (#15107)
@react-router/node - Honor Node writable backpressure in writeReadableStreamToWritable and writeAsyncIterableToWritable (#15071)
'drain' when writable.write() returns false instead of letting chunks accumulate in the writable's internal buffer.@react-router/serve - Normalize assetsBuildDirectory path separators in react-router-serve so Windows-built server artifacts can serve /assets/* correctly when run on Linux. (#14982)
Full Changelog: v7.15.1...v7.16.0
This should allow you to consolidate usages of a bunch of different hooks which will likely be marked deprecated later on in v8 and potentially remove…
Date: 2026-05-14
useRouterState (unstable)Following our Less is More design goal, this release includes a new unstable_useRouterState() hook (Framework + Data Mode) that consolidates access to active and pending router states (RFC, Roadmap Issue).
This should allow you to consolidate usages of a bunch of different hooks which will likely be marked deprecated later on in v8 and potentially removed in an eventual v9:
let { active, pending } = unstable_useRouterState();
// Active is always populated with the current location
active.location; // replaces `useLocation()`
active.searchParams; // replaces `useSearchParams()[0]`
active.params; // replaces `useParams()`
active.matches; // replaces `useMatches()`
active.type; // replaces `useNavigationType()`
// Pending is only populated during a navigation
pending.location; // replaces `useNavigation().location`
pending.searchParams; // equivalent to `new URLSearchParams(useNavigation().search)`
pending.params; // Not directly accessible today
pending.matches; // Not directly accessible today
pending.type; // Not directly accessible today
pending.state; // replaces `useNavigation().state`
pending.formMethod; // replaces useNavigation().formMethod
pending.formAction; // replaces useNavigation().formAction
pending.formEncType; // replaces useNavigation().formEncType
pending.formData; // replaces useNavigation().formData
pending.json; // replaces useNavigation().json
pending.text; // replaces useNavigation().text
react-router - Memoize useFetchers to return a stable identity and only change if fetchers changed (#15028)react-router - Update router to operate on fetcher Maps in an immutable manner to avoid delayed React renders from potentially reading an updated but not yet committed Map. This could result in brief flickers in some fetcher-driven optimistic UI scenarios (#15028)react-router - Fix serverLoader() returning stale SSR data when a client navigation aborts pending hydration before the hydration clientLoader resolves (#15022)react-router - Fix RouterProvider onError callback not being called for synchronous initial loader errors in SPA mode (#15039) (#14942)react-router - Internal refactor to consolidate mutation request detection through shared utility (#15033)@react-router/dev - Fix basename conflicting with app directory name when Vite base is set (#15027)
base config and React Router basename both match the app directory name (e.g. base: "/app/", basename: "/app/"), Vite would strip the base prefix from server-build virtual module import paths, causing "Failed to load url /root.tsx" errors/@fs/ absolute paths for those imports to bypass Vite's base-stripping logic⚠️ Unstable features are not recommended for production use
react-router - Add a new unstable_useRouterState() hook that consolidates access to active and pending router states (RFC: #12358) (#15017)
Full Changelog: v7.15.0...v7.15.1
…next month or two. These flag/prop renames are breaking changes if you've already opted into the unstable APIs so please make sure you make the approp…
Date: 2026-05-05
We've stabilized a bunch of APIs in this release in preparation for a React Router v8 release hopefully in the next month or two. These flag/prop renames are breaking changes if you've already opted into the unstable APIs so please make sure you make the appropriate changes if so.
future.unstable_passThroughRequests → future.v8_passThroughRequestsfuture.unstable_subResourceIntegrity → top-level config.subResourceIntegrityprerender.unstable_concurrency → prerender.concurrencyunstable_url → url (loader, action, middleware, instrumentation args)unstable_instrumentations → instrumentations
ServerInstrumentation, ClientInstrumentation, etc.)unstable_pattern → pattern (loader, action, middleware, instrumentation args)unstable_defaultShouldRevalidate → defaultShouldRevalidateunstable_useTransitions → useTransitionsunstable_mask → mask (on <Link>, useLinkClickHandler, useNavigate, and Location)We've added a handful of route matching optimizations in this release for Framework and Data mode. The changes are mostly related to caching the internal flattened/ranked route branches and reducing additional calls to matchRoutes along the critical path. This should result in improved performance during both server-side request handling and client-side navigations.
react-router - Stabilize unstable_defaultShouldRevalidate as defaultShouldRevalidate on <Link>, <Form>, useLinkClickHandler, useSubmit, fetcher.submit, and setSearchParams (14999)
react-router - Stabilize the instrumentation APIs (14999)
unstable_instrumentations is now instrumentationsunstable_pattern is now patternunstable_ServerInstrumentation, unstable_ClientInstrumentation, unstable_InstrumentRequestHandlerFunction, unstable_InstrumentRouterFunction, unstable_InstrumentRouteFunction, and unstable_InstrumentationHandlerResult types have had their unstable_ prefixes removedreact-router - Stabilize unstable_mask as mask on <Link>, useLinkClickHandler, and useNavigate, and rename the corresponding Location.unstable_mask field to Location.mask (14999)
react-router - Stabilize the unstable_normalizePath option on staticHandler.query and staticHandler.queryRoute as normalizePath (14999)
react-router - Stabilize future.unstable_passThroughRequests as future.v8_passThroughRequests (14999)
react-router - Remove unstable_subResourceIntegrity from the runtime FutureConfig type; the flag is now controlled by the top-level subResourceIntegrity option in react-router.config.ts (14999)
react-router - Stabilize unstable_url as url on loader, action, and middleware function args (14999)
react-router - Stabilize unstable_useTransitions as useTransitions on <BrowserRouter>, <HashRouter>, <HistoryRouter>, <MemoryRouter>, <Router>, <RouterProvider>, <HydratedRouter>, and useLinkClickHandler (14999)
@react-router/dev - Stabilize future.unstable_passThroughRequests as future.v8_passThroughRequests (14999)
@react-router/dev - Stabilize prerender.unstable_concurrency as prerender.concurrency (14999)
@react-router/dev - Stabilize future.unstable_subResourceIntegrity as a top-level subResourceIntegrity config option in react-router.config.ts (14999)
react-router - Add nonce to <Scripts> <link rel="modulepreload"> elements (if provided) (af5d49b)react-router - Fix a bug with unstable_defaultShouldRevalidate={false} where parent routes that did not export a shouldRevalidate function could be incorrectly included in the single fetch call for new child route data (#15012)react-router - Mark mask as an optional field in Location for easier mocking in unit tests (#14999)react-router - Improve server-side route matching performance by pre-computing flattened/cached route branches (#14967)
react-router - Cache flattened/ranked route branches to optimize server-side route matching (#14967)react-router - Improve route matching performance in Framework/Data Mode (#14971)
matchRoutes in data router scenarios
7.6.0 (#13562)matches but always updating match.route to the latest route in the manifestFull Changelog: v7.14.2...v7.15.0
⚠️ This is a breaking change if you have begun using the unstable_reactRouterRSC Vite plugin - please install @vitejs/plugin-react and add the react p…
Date: 2026-04-21
react-router - Remove the un-documented custom error serialization logic from the internal turbo-stream implementation. React Router only automatically handles serialization of Error and it's standard subtypes (SyntaxError, TypeError, etc.). (#14992)
react-router - Properly handle parent middleware redirects during fetcher.load (#14974)
react-router - Remove redundant Omit<RouterProviderProps, "flushSync"> from react-router/dom RouterProvider (#14874)
react-router - Improved types for generatePath's param arg (#14984)
Type errors when required params are omitted:
// Before
// Passes type checks, but throws at runtime 💥
generatePath(":required", { required: null });
// After
generatePath(":required", { required: null });
// ^^^^^^^^ Type 'null' is not assignable to type 'string'.ts(2322)
Allow omission of optional params:
// Before
generatePath(":optional?", {});
// ^^ Property 'optional' is missing in type '{}' but required in type '{ optional: string | null | undefined; }'.ts(2741)
// After
generatePath(":optional?", {});
Allows extra keys:
// Before
generatePath(":a", { a: "1", b: "2" });
// ^ Object literal may only specify known properties, and 'b' does not exist in type '{ a: string; }'.ts(2353)
// After
generatePath(":a", { a: "1", b: "2" });
@react-router/dev - Fix typegen for layouts without pages (#14875)
pages: ; in .react-router/types/+routes.ts when a route corresponded to 0 pagespages: never; is correctly generated for those cases⚠️ Unstable features are not recommended for production use
@react-router/dev - For unstable_reactRouterRSC Vite plugin consumers, require @vitejs/plugin-react in user Vite config, and more reliably split route modules (#14965)
unstable_reactRouterRSC Vite plugin - please install @vitejs/plugin-react and add the react plugin to your Vite plugins array.Full Changelog: v7.14.1...v7.14.2
react-router - Fix a potential race condition that can occur when rendering a HydrateFallback and initial loaders land before the router.subscribe cal
Date: 2026-04-13
react-router - Fix a potential race condition that can occur when rendering a HydrateFallback and initial loaders land before the router.subscribe call happens in the RouterProvider layout effect (#14497)react-router - Normalize double-slashes in redirect paths (#14962)@react-router/dev - Add TypeScript 6 support to peer dependency ranges (#14935)Full Changelog: v7.14.0...v7.14.1
⚠️ This is a breaking change if you have already adopted RSC Framework Mode in it's unstable state - you will need to update your route modules to exp…
Date: 2026-04-02
react-router - Remove recursion from vendored turbo-stream v2 implementation allowing for encoding/decoding of large payloads (#14838)react-router - Fix encodeViaTurboStream memory leak via unremoved AbortSignal listener (#14900)@react-router/dev - Support for prerendering multiple server bundles with v8_viteEnvironmentApi (#14921)⚠️ Unstable features are not recommended for production use
@react-router/dev - Pre-rendering and SPA Mode support for RSC Framework Mode (#14907)@react-router/dev - Update react-router reveal to support RSC Framework Mode for entry.client, entry.rsc, entry.ssr (#14904)react-router - Support <Link prefetch> in RSC Framework Mode (#14902)react-router - Add support for new route module exports in unstable RSC Framework Mode (#14901)
⚠️ This is a breaking change if you have already adopted RSC Framework Mode in it's unstable state - you will need to update your route modules to export the new annotations
The following route module components have their own mutually exclusive server component counterparts:
| Client Component export | Server Component export |
|---|---|
default |
ServerComponent |
ErrorBoundary |
ServerErrorBoundary |
Layout |
ServerLayout |
HydrateFallback |
ServerHydrateFallback |
If you were previously exporting a ServerComponent, your ErrorBoundary, Layout, and HydrateFallback were also implicitly server components
If you want to keep those as server components - rename them and prefix them with Server
If you were previously importing the implementations of those components from a client module, you can inline them
// Before
import { ErrorBoundary as ClientErrorBoundary } from "./client";
export function ServerComponent() {
// ...
}
export function ErrorBoundary() {
return <ClientErrorBoundary />;
}
export function Layout() {
// ...
}
export function HydrateFallback() {
// ...
}
// After
export function ServerComponent() {
// ...
}
export function ErrorBoundary() {
// previous implementation of ClientErrorBoundary, this is now a client component
}
export function ServerLayout() {
// rename previous Layout export to ServerLayout to make it a server component
}
export function ServerHydrateFallback() {
// rename previous HydrateFallback export to ServerHydrateFallback to make it a server component
}
Full Changelog: v7.13.2...v7.14.0
Nothing published for this version
By default, React Router normalizes the request.url passed to your loader, action, and middleware functions by removing React Router's internal implem
Date: 2026-03-23
By default, React Router normalizes the request.url passed to your loader, action, and middleware functions by removing React Router's internal implementation details (.data suffixes, index + _routes query params). This release introduces a new future.unstable_passThroughRequests flag to disable this normalization and pass the raw HTTP request instance to your handlers.
In addition to reducing server-side overhead by eliminating multiple new Request() calls on the critical path, this also provides additional visibility to your route handlers/instrumentations allowing you to differentiate document from data requests.
If you were previously relying on the normalization of request.url, you can switch to use the new sibling unstable_url parameter which contains a URL instance representing the normalized location:
// ❌ Before: you could assume there was no `.data` suffix in `request.url`
export async function loader({ request }: Route.LoaderArgs) {
let url = new URL(request.url);
if (url.pathname === "/path") {
// This check will fail with the flag enabled because the `.data` suffix will
// exist on data requests
}
}
// ✅ After: use `unstable_url` for normalized routing logic and `request.url`
// for raw routing logic
export async function loader({ request, unstable_url }: Route.LoaderArgs) {
if (unstable_url.pathname === "/path") {
// This will always have the `.data` suffix stripped
}
// And now you can distinguish between document versus data requests
let isDataRequest = new URL(request.url).pathname.endsWith(".data");
}
unstable_url parameterWe have added a new unstable_url: URL parameter to route handler methods (loader, action, middleware, etc.) that contains the normalized URL the application is navigating to or fetching with React Router implementation details removed (.datasuffix, index/_routes query params).
This parameter is primarily needed when adopting the new future.unstable_passthroughRequests future flag as a way to continue accessing the normalized URL. If you don't have the flag enabled, then unstable_url will match request.url.
react-router - Fix clientLoader.hydrate when an ancestor route is also hydrating a clientLoader (#14835)react-router - Fix type error when passing Framework Mode route components using Route.ComponentProps to createRoutesStub (#14892)react-router - Fix percent encoding in relative path navigation (#14786)react-router - Internal refactor to consolidate framework-agnostic/React-specific route type layers - no public API changes (#14765)@react-router/dev - Fix react-router dev crash when Unix socket files exist in the project root (#14854)@react-router/dev - Escape redirect locations in pre-rendered redirect HTML (#14880)create-react-router - replace chalk with picocolors (#14837)⚠️ Unstable features are not recommended for production use
react-router - Sync protocol validation to RSC flows (#14882)react-router - Add future.unstable_passThroughRequests flag (#14775)react-router - Add a new unstable_url: URL parameter to route handler methods (loader, action, middleware, etc.) representing the normalized URL the application is navigating to or fetching, with React Router implementation details removed (.datasuffix, index/_routes query params) (#14775)Full Changelog: v7.13.1...v7.13.2
Nothing published for this version
This release includes a new API which brings first-class support for URL masking to Framework/Data Mode (RFC). This allows the same type of UI you cou
Date: 2026-02-23
This release includes a new <Link unstable_mask> API which brings first-class support for URL masking to Framework/Data Mode (RFC). This allows the same type of UI you could achieve in Declarative Mode via manual backgroundLocation management. That example has been converted to Data Mode using the new API here.
react-router - Clear timeout when turbo-stream encoding completes (#14810)react-router - Improve error message when Origin header is invalid (#14743)react-router - Fix matchPath optional params matching without a "/" separator. (#14689)
matchPath("/users/:id?", "/usersblah") now returns nullmatchPath("/test_route/:part?", "/test_route_more") now returns null.react-router - Fix HydrateFallback rendering during initial lazy route discovery with matching splat route (#14740)react-router - Preserve query parameters and hash on manifest version mismatch reload (#14813)⚠️ Unstable features are not recommended for production use
react-router - RSC: fix null reference exception in bad codepath leading to invalid route tree comparisons (#14780)react-router - RSC: add unstable_getRequest API (#14758)react-router - RSC: Update failed origin checks to return a 400 status and appropriate UI instead of a generic 500 (#14755)react-router - Add support for <Link unstable_mask> in Framework/Data Mode which allows users to navigate to a URL in the router but "mask" the URL displayed in the browser (#14716)
This is useful for contextual routing usages such as displaying an image in a modal on top of a gallery, but displaying a browser URL directly to the image that can be shared and loaded without the contextual gallery in the background
The masked location, if present, will be available on useLocation().unstable_mask so you can detect whether you are currently masked or not
Masked URLs only work for SPA use cases, and will be removed from history.state during SSR
This provides a first-class API to mask URLs in Framework/Data Mode to achieve the same behavior you could do in Declarative Mode via manual backgroundLocation management.
// routes/gallery.tsx
export function clientLoader({ request }: Route.LoaderArgs) {
let sp = new URL(request.url).searchParams;
return {
images: getImages(),
// When the router location has the image param, load the modal data
modalImage: sp.has("image") ? getImage(sp.get("image")!) : null,
};
}
export default function Gallery({ loaderData }: Route.ComponentProps) {
return (
<>
<GalleryGrid>
{loaderData.images.map((image) => (
<Link
key={image.id}
{/* Navigate the router to /galley?image=N */}}
to={`/gallery?image=${image.id}`}
{/* But display /images/N in the URL bar */}}
unstable_mask={`/images/${image.id}`}
>
<img src={image.url} alt={image.alt} />
</Link>
))}
</GalleryGrid>
{/* When the modal data exists, display the modal */}
{data.modalImage ? (
<dialog open>
<img src={data.modalImage.url} alt={data.modalImage.alt} />
</dialog>
) : null}
</>
);
}
Full Changelog: v7.13.0...v7.13.1
Nothing published for this version
react-router - Add crossOrigin prop to Links component
Date: 2026-01-23
react-router - Add crossOrigin prop to Links component (#14687)react-router - Fix double slash normalization for useNavigate paths with a colon (#14718)react-router - Fix missing nonce on inline criticalCss (#14691)react-router - Update failed origin checks to return a 400 status instead of a 500 (#14737)react-router - Loosen allowedActionOrigins glob check so ** matches all domains (#14722)@react-router/dev - Bump @remix-run/node-fetch-server dep (#14704)@react-router/fs-routes - Fix route file paths when routes directory is outside of the app directory (#13937)Full Changelog: v7.12.0...v7.13.0
Nothing published for this version
This release addresses 3 security vulnerabilities:
Date: 2026-01-07
This release addresses 3 security vulnerabilities:
react-router - Add additional layer of CSRF protection by rejecting submissions to UI routes from external origins (#14708)
allowedActionOrigins config field in react-router.config.ts where you can specify external originsreact-router - Fix generatePath when used with suffixed params (i.e., /books/:id.json) (#14269)react-router - Escape HTML in scroll restoration keys (#14705)react-router - Validate redirect locations (#14706)@react-router/dev - Fix Maximum call stack size exceeded errors when HMR is triggered against code with cyclic imports (#14522)@react-router/dev - Skip SSR middleware in vite preview server for SPA mode (#14673)⚠️ Unstable features are not recommended for production use
react-router - Preserve clientLoader.hydrate=true when using <HydratedRouter unstable_instrumentations> (#14674)react-router - Pass <Scripts nonce> value through to the underlying importmap script tag when using future.unstable_subResourceIntegrity (#14675)react-router - Export UNSAFE_createMemoryHistory and UNSAFE_createHashHistory alongside UNSAFE_createBrowserHistory for consistency (#14663)
unstable_HistoryRouter migrate from v6->v7 so they can adopt the newer APIs@react-router/dev - Add a new future.unstable_trailingSlashAwareDataRequests flag to provide consistent behavior of request.pathname inside middleware, loader, and action functions on document and data requests when a trailing slash is present in the browser URL. (#14644)
Currently, your HTTP and request pathnames would be as follows for /a/b/c and /a/b/c/
URL /a/b/c |
HTTP pathname | request pathname` |
|---|---|---|
| Document | /a/b/c |
/a/b/c ✅ |
| Data | /a/b/c.data |
/a/b/c ✅ |
URL /a/b/c/ |
HTTP pathname | request pathname` |
|---|---|---|
| Document | /a/b/c/ |
/a/b/c/ ✅ |
| Data | /a/b/c.data |
/a/b/c ⚠️ |
With this flag enabled, these pathnames will be made consistent though a new _.data format for client-side .data requests:
URL /a/b/c |
HTTP pathname | request pathname` |
|---|---|---|
| Document | /a/b/c |
/a/b/c ✅ |
| Data | /a/b/c.data |
/a/b/c ✅ |
URL /a/b/c/ |
HTTP pathname | request pathname` |
|---|---|---|
| Document | /a/b/c/ |
/a/b/c/ ✅ |
| Data | /a/b/c/_.data ⬅️ |
/a/b/c/ ✅ |
This a bug fix but we are putting it behind an opt-in flag because it has the potential to be a "breaking bug fix" if you are relying on the URL format for any other application or caching logic
Enabling this flag also changes the format of client side .data requests from /_root.data to /_.data when navigating to / to align with the new format - This does not impact the request pathname which is still / in all cases
Full Changelog: v7.11.0...v7.12.0
Nothing published for this version
We've added vite preview support and stabilized the client-side onError API - please make the appropriate changes if you've adopted the unstable_onErr
Date: 2025-12-17
We've added vite preview support and stabilized the client-side onError API - please make the appropriate changes if you've adopted the unstable_onError API already in a prior release.
vite preview SupportWe've added support for vite preview when using Framework mode to make it easy to preview your production build.
onErrorThe existing <RouterProvider unstable_onError>/<HydratedRouter unstable_onError> APIs have been stabilized as <RouterProvider onError>/<HydratedRouter onError>. Please see the Error Reporting docs for more information.
We've added initial unstable support for call-site revalidation opt-out via a new unstable_defaultShouldRevalidate flag (RFC). This flag is available on all navigation/fetcher submission APIs to alter standard revalidation behavior. If any routes include a shouldRevalidate function, then the flag value will be passed to that function so the route has the final say on revalidation behavior.
<Form method="post" unstable_defaultShouldRevalidate={false} />
submit(data, { method: "post", unstable_defaultShouldRevalidate: false })
<fetcher.Form method="post" unstable_defaultShouldRevalidate={false} />
fetcher.submit(data, { method: "post", unstable_defaultShouldRevalidate: false })
This flag is also available on non-submission navigational use cases - for example, you may want to opt-out of revalidation when adding a search param that doesn't impact the UI:
<Link to="?analytics-param=1" unstable_defaultShouldRevalidate={false} />;
navigate("?analytics-param=1", { unstable_defaultShouldRevalidate: false });
setSearchParams(params, { unstable_defaultShouldRevalidate: false });
react-router - Stabilize <HydratedRouter onError>/<RouterProvider onError> (#14546)@react-router/dev - Add vite preview support (#14507)react-router - Fix unstable_useTransitions prop on <Router> component to permit omission for backwards compatibility (#14646)react-router - Allow redirects to be returned from client side middleware (#14598)react-router - Handle dataStrategy implementations that return insufficient result sets by adding errors for routes without any available result (#14627)@react-router/serve - Update compression and morgan dependencies to address on-headers CVE: GHSA-76c9-3jph-rj3q (#14652)⚠️ Unstable features are not recommended for production use
react-router - RSC: Support for throwing data() and Response from server component render phase (#14632)
data() insteadreact-router - RSC: Support for throwing redirect Response's at render time (#14596)react-router - RSC: routeRSCServerRequest replace fetchServer with serverResponse (#14597)@react-router/dev - RSC (Framework mode): Manual chunking for react and react-router deps (#14655)@react-router/dev - RSC (Framework mode): Optimize react-server-dom-webpack if in project package.json (#14656)@react-router/{dev,serve} - RSC (Framework mode): Support custom entrypoints (#14643)react-router - Add a new unstable_defaultShouldRevalidate flag to various APIs to allow opt-ing out of standard revalidation behaviors (#14542)Full Changelog: v7.10.1...v7.11.0
Nothing published for this version
react-router - Update the useOptimistic stub we provide for React 18 users to use a stable setter function to avoid potential useEffect loops - specif
Date: 2025-12-04
react-router - Update the useOptimistic stub we provide for React 18 users to use a stable setter function to avoid potential useEffect loops - specifically when using <Link viewTransition> (#14628)@react-router/dev - Import ESM package pkg-types with a dynamic import() to fix issues on Node 20.18 (#14624)@react-router/dev - Update valibot dependency to ^1.2.0 to address GHSA-vqpr-j7v3-hqw9 (#14608)Full Changelog: v7.10.0...v7.10.1
Nothing published for this version
⚠️ This is a breaking change if you have begun using fetcher.unstable_reset() - please update your code to use fetcher.reset()
Date: 2025-12-02
We've stabilized a handful of existing APIs and future flags in this release, please make the appropriate changes if you'd adopted any of these APIs in their unstable state!
future.v8_splitRouteModulesThe existing future.unstable_splitRouteModules flag has been stabilized as future.v8_splitRouteModules in react-router.config.ts. Please see the docs for more information on adopting this flag.
future.v8_viteEnvironmentApiThe existing future.unstable_viteEnvironmentApi flag has been stabilized as future.v8_viteEnvironmentApi in react-router.config.ts. Please see the docs for more information on adopting this flag.
fetcher.reset()The existing fetcher.unstable_reset() API has been stabilized as fetcher.reset().
DataStrategyMatch.shouldCallHandler()The existing low-level DataStrategyMatch.unstable_shouldCallHandler()/DataStrategyMatch.unstable_shouldRevalidateArgs APIs have been stabilized as DataStrategyMatch.shouldCallHandler()/DataStrategyMatch.shouldRevalidateArgs. Please see the docs for information about using a custom dataStrategy and how to migrate away from the deprecated DataStrategyMatch.shouldLoad API if you are using that today.
react-router - Stabilize fetcher.reset() (#14545)
fetcher.unstable_reset() - please update your code to use fetcher.reset()react-router - Stabilize the dataStrategy match.shouldCallHandler()/match.shouldRevalidateArgs APIs (#14592)
match.shouldLoad API is now marked deprecated in favor of these more powerful alternativesmatch.unstable_shouldCallHandler()/match.unstable_shouldRevalidateArgs - please update your code to use match.shouldCallHandler()/match.shouldRevalidateArgs@react-router/dev - Stabilize future.v8_splitRouteModules, replacing future.unstable_splitRouteModules (#14595)
future.unstable_splitRouteModules - please update your react-router.config.ts@react-router/dev - Stabilize future.v8_viteEnvironmentApi, replacing future.unstable_viteEnvironmentApi (#14595)
future.unstable_viteEnvironmentApi - please update your react-router.config.tsreact-router - Fix a Framework Mode bug where the defaultShouldRevalidate parameter to shouldRevalidate would not be correct after action returned a 4xx/5xx response (true when it should have been false) (#14592)
shouldRevalidate function relied on that parameter, you may have seen unintended revalidationsreact-router - Fix fetcher.submit failing with plain objects containing a tagName property (#14534)react-router - Fix the promise returned from useNavigate in Framework/Data Mode so that it properly tracks the duration of popstate navigations (i.e., navigate(-1)) (#14524)react-router - Preserve statusText on the ErrorResponse instance when throwing data() from a route handler (#14555)react-router - Optimize href() to avoid backtracking regex on splat (#14329)@react-router/dev - Fix internal type error in useRoute types that surfaces when skipLibCheck is disabled (#14577)@react-router/dev - Load environment variables before evaluating routes.ts (#14446)
For example, you can now compute your routes based on VITE_-prefixed environment variables
// app/routes.ts
import { type RouteConfig, route } from "@react-router/dev/routes";
const routes: RouteConfig = [];
// Only add the route when VITE_ENV_ROUTE is set
if (import.meta.env.VITE_ENV_ROUTE === "my-route") {
routes.push(route("my-route", "routes/my-route.tsx"));
}
export default routes;
⚠️ Unstable features are not recommended for production use
react-router - Add unstable_pattern to the parameters for client side unstable_onError (#14573)react-router - Refactor how unstable_onError is called internally by RouterProvider to avoid potential strict mode issues (#14573)react-router - Add new unstable_useTransitions flag to routers to give users control over the usage of React.startTransition and React.useOptimistic (#14524)
<HydratedRouter unstable_transition>/<RouterProvider unstable_transition>React.startTransitionReact.startTransitiontrue if you run into this scenario to get the enhanced useOptimistic behavior (requires React 19)true
React.startTransition (as they are without the flag)Link/Form navigations will be wrapped in React.startTransition
useNavigate/useSubmit if you wish to opt out of this outer React.startTransition call for the navigationReact.useOptimistic (i.e., useNavigation(), useFetchers(), etc.)
false
React.startTransition or React.useOptimistic on any navigations or state changes<BrowserRouter unstable_useTransitions>React.startTransitiontrue
React.startTransition (as they are without the flag)Link/Form navigations will be wrapped in React.startTransitionfalse
React.startTransition on any navigations or state changesFull Changelog: v7.9.6...v7.10.0
Nothing published for this version
Nothing published for this version
This release addresses 1 security vulnerability:
Date: 2025-11-13
This release addresses 1 security vulnerability:
react-router - Properly handle ancestor thrown middleware errors before next() on fetcher submissions (#14517)react-router - Fix issue with splat routes interfering with multiple calls to patchRoutesOnNavigation (#14487)react-router - Normalize double-slashes in resolvePath (#14529)@react-router/dev - Use a dynamic import() to load ESM-only p-map dependency to avoid issues on Node 20.18 and below (#14492)@react-router/dev - Short circuit HEAD document requests before calling renderToPipeableStream in the default entry.server.tsx to more closely align with the spec (#14488)⚠️ Unstable features are not recommended for production use
react-router - Add location/params as arguments to client-side unstable_onError to permit enhanced error reporting (#14509)
⚠️ This is a breaking change if you've already adopted unstable_onError
The second parameter has changed to an object including errorInfo, location, and params:
// <RouterProvider unstable_onError={errorHandler} />
// <HydratedRouter unstable_onError={errorHandler} />
// Before
function errorHandler(error: unknown, errorInfo?: React.errorInfo) {
/*...*/
}
// After
function errorHandler(
error: unknown,
info: {
location: Location;
params: Params;
errorInfo?: React.ErrorInfo;
},
) {
/*...*/
}
Full Changelog: v7.9.5...v7.9.6
Nothing published for this version
Nothing published for this version
This release adds new unstable_instrumentation APIs that will allow you to add runtime instrumentation logic to various aspects of your application (s
Date: 2025-10-29
This release adds new unstable_instrumentation APIs that will allow you to add runtime instrumentation logic to various aspects of your application (server handler, client navigations/fetches, loaders, actions, middleware, route.lazy). For more information, please see the docs.
react-router - Ensure action handlers run for routes with middleware even if no loader is present (#14443)@react-router/dev - Ensure route navigation doesn't remove CSS link elements used by dynamic imports (#14463)@react-router/dev - Typegen: only register route module types for routes within the app directory (#14439)⚠️ Unstable features are not recommended for production use
react-router - Move unstable_RSCHydratedRouter and utils to react-router/dom export (#14457)
react-router - Add a type-safe handle field to unstable_useRoute() (#14462)
For example:
// app/routes/admin.tsx
const handle = { hello: "world" };
// app/routes/some-other-route.tsx
export default function Component() {
const admin = useRoute("routes/admin");
if (!admin) throw new Error("Not nested within 'routes/admin'");
console.log(admin.handle);
// ^? { hello: string }
}
react-router - Add unstable_instrumentations API to allow users to add observability to their apps by instrumenting route loaders, actions, middlewares, lazy, as well as server-side request handlers and client side navigations/fetches (#14412)
entry.server.tsx: export const unstable_instrumentations = [...]entry.client.tsx: <HydratedRouter unstable_instrumentations={[...]} />createBrowserRouter(routes, { unstable_instrumentations: [...] })react-router - Add a new unstable_pattern parameter to loaders/actions/middleware which contains the un-interpolated route pattern (i.e., /blog/:slug) which is useful for aggregating logs/metrics by route in instrumentation code (#14412)
@react-router/dev - Introduce a prerender.unstable_concurrency option, to support running the pre-rendering concurrently, potentially speeding up the build (#14380)
Full Changelog: v7.9.4...v7.9.5
Nothing published for this version
This release addresses 1 security vulnerability:
Date: 2025-10-08
This release addresses 1 security vulnerability:
useRoute() (unstable)This release includes a new unstable_useRoute() hook that provides a type-safe way to access route loaderData/actionData from a specific route in Framework Mode. Think if it like a better version of useRouteLoaderData that works with the typegen system and also supports actionData. Check out the changelog entry below for more information.
@react-router/dev - Update valibot dependency to ^1.1.0 (#14379)@react-router/node - Validate format of incoming session ids in createFileSessionStorage (#14426)⚠️ Unstable features are not recommended for production use
react-router - handle external redirects in from server actions (#14400)
react-router - New (unstable) useRoute hook for accessing data from specific routes (#14407)
For example, let's say you have an admin route somewhere in your app and you want any child routes of admin to all have access to the loaderData and actionData from admin.
// app/routes/admin.tsx
import { Outlet } from "react-router";
export const loader = () => ({ message: "Hello, loader!" });
export const action = () => ({ count: 1 });
export default function Component() {
return (
<div>
{/* ... */}
<Outlet />
{/* ... */}
</div>
);
}
You might even want to create a reusable widget that all of the routes nested under admin could use:
import { unstable_useRoute as useRoute } from "react-router";
export function AdminWidget() {
// How to get `message` and `count` from `admin` route?
}
In framework mode, useRoute knows all your app's routes and gives you TS errors when invalid route IDs are passed in:
export function AdminWidget() {
const admin = useRoute("routes/dmin");
// ^^^^^^^^^^^
}
useRoute returns undefined if the route is not part of the current page:
export function AdminWidget() {
const admin = useRoute("routes/admin");
if (!admin) {
throw new Error(`AdminWidget used outside of "routes/admin"`);
}
}
Note: the root route is the exception since it is guaranteed to be part of the current page.
As a result, useRoute never returns undefined for root.
loaderData and actionData are marked as optional since they could be accessed before the action is triggered or after the loader threw an error:
export function AdminWidget() {
const admin = useRoute("routes/admin");
if (!admin) {
throw new Error(`AdminWidget used outside of "routes/admin"`);
}
const { loaderData, actionData } = admin;
console.log(loaderData);
// ^? { message: string } | undefined
console.log(actionData);
// ^? { count: number } | undefined
}
If instead of a specific route, you wanted access to the current route's loaderData and actionData, you can call useRoute without arguments:
export function AdminWidget() {
const currentRoute = useRoute();
currentRoute.loaderData;
currentRoute.actionData;
}
This usage is equivalent to calling useLoaderData and useActionData, but consolidates all route data access into one hook: useRoute.
Note: when calling useRoute() (without a route ID), TS has no way to know which route is the current route.
As a result, loaderData and actionData are typed as unknown.
If you want more type-safety, you can either narrow the type yourself with something like zod or you can refactor your app to pass down typed props to your AdminWidget:
export function AdminWidget({
message,
count,
}: {
message: string;
count: number;
}) {
/* ... */
}
Full Changelog: v7.9.3...v7.9.4
Nothing published for this version
react-router - Fix Data Mode regression causing a 404 during initial load in when middleware exists without any loader functions
Date: 2025-09-26
react-router - Fix Data Mode regression causing a 404 during initial load in when middleware exists without any loader functions (#14393)react-router - Do not try to use turbo-stream to decode CDN errors that never reached the server (#14385)
ErrorBoundary instead of a generic "Unable to decode turbo-stream response" errorFull Changelog: v7.9.2...v7.9.3
Nothing published for this version
This release contains a handful of bug fixes, but we think you'll be most excited about the new unstable stuff 😉.
Date: 2025-09-24
This release contains a handful of bug fixes, but we think you'll be most excited about the new unstable stuff 😉.
This release includes our first release of unstable support for RSC in Framework Mode! You can read more about it in our blog post and the docs.
This release also includes a new (long-requested) fetcher.unstable_reset() API to reset fetchers back to their initial idle state.
react-router - Ensure client-side router runs client middleware during initialization data load (if required) even if no loaders exist (#14348)react-router - Fix middleware prop not being supported on <Route> when used with a data router via createRoutesFromElements (#14357)react-router - Update createRoutesStub to work with middleware (#14348)
<RoutesStub future={{ v8_middleware: true }} /> flag to enable the proper context typereact-router - Update Lazy Route Discovery manifest requests to use a singular comma-separated paths query param instead of repeated p query params (#14321)
react-router - Fail gracefully on manifest version mismatch logic if sessionStorage access is blocked (#14335)react-router - Update useOutlet returned element to have a stable identity in-between route changes (#13382)react-router - Handle encoded question mark and hash characters in ancestor splat routes (#14249)@react-router/dev - Switch internal vite plugin Response logic to use @remix-run/node-fetch-server (#13927)@react-router/dev - Fix presets future flags being ignored during config resolution (#14369)⚠️ Unstable features are not recommended for production use
react-router - Add fetcher.unstable_reset() API (#14206)react-router - In RSC Data Mode, handle SSR'd client errors and re-try in the browser (#14342)react-router - Enable full transition support for the RSC router (#14362)@react-router/dev - Add unstable support for RSC Framework Mode (#14336)@react-router/serve - Disable compression() middleware in RSC framework mode (#14381)Full Changelog: v7.9.1...v7.9.2
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fix internal Future interface naming from middleware -> v8_middleware
Date: 2025-09-12
Future interface naming from middleware -> v8_middleware (#14327)Full Changelog: v7.9.0...v7.9.1
Nothing published for this version
This release addresses 1 security vulnerability:
Date: 2025-09-12
This release addresses 1 security vulnerability:
We have removed the unstable_ prefix from the following APIs and they are now considered stable and ready for production use:
RouterContextProvidercreateContextcreateBrowserRouter getContext option<HydratedRouter> getContext propPlease see the Middleware Docs, the Middleware RFC, and the Client-side Context RFC for more information.
react-router - Update href() to correctly process routes that have an extension after the parameter or are a single optional parameter (#13797)react-router - Escape HTML in meta() JSON-LD content (#14316)⚠️ Unstable features are not recommended for production use
react-router - RSC: Add react-server Await component implementation (#14261)react-router - RSC: Fix hydration errors for routes that only have client loaders when using RSC in Data Mode along with a custom basename (#14264)react-router - RSC: Make href function available in a react-server context (#14262)react-router - RSC: Decode each time getPayload() is called to allow for "in-context" decoding and hoisting of contextual assets (#14248)Full Changelog: v7.8.2...v7.9.0
Nothing published for this version
Nothing published for this version
react-router - Maintain ReadonlyMap and ReadonlySet types in server response data.
Date: 2025-08-22
react-router - Maintain ReadonlyMap and ReadonlySet types in server response data. (#13092)react-router - Fix basename usage without a leading slash in data routers (#11671)react-router - Fix TypeError if you throw from patchRoutesOnNavigation when no partial matches exist (#14198)react-router - Properly escape interpolated param values in generatePath() (#13530)@react-router/dev - Fix potential memory leak in default entry.server (#14200)⚠️ Unstable features are not recommended for production use
Client-side onError
react-router - Add <RouterProvider unstable_onError>/<HydratedRouter unstable_onError> prop for client side error reporting (#14162)Middleware
react-router - Delay serialization of .data redirects to 202 responses until after middleware chain (#14205)react-router - Update client middleware so it returns the dataStrategy results up the chain allowing for more advanced post-processing middleware (#14151, #14212)react-router - Remove Data Mode future.unstable_middleware flag from createBrowserRouter (#14213)
getLoadContext type behavior changeRSC
react-router - Allow opting out of revalidation on server actions with hidden $SKIP_REVALIDATION input (#14154)Full Changelog: v7.8.1...v7.8.2
Nothing published for this version
Nothing published for this version
react-router - Fix usage of optional path segments in nested routes defined using absolute paths
Date: 2025-08-15
react-router - Fix usage of optional path segments in nested routes defined using absolute paths (#14135)react-router - Fix optional static segment matching in matchPath (#11813)react-router - Fix pre-rendering when a basename is set with ssr:false (#13791)react-router - Properly convert returned/thrown data() values to Response instances via Response.json() in resource routes and middleware (#14159, #14181)@react-router/dev - Update generated Route.MetaArgs type so loaderData is only potentially undefined when an ErrorBoundary export is present (#14173)⚠️ Unstable features are not recommended for production use
Middleware
react-router - Bubble client pre-next middleware errors to the shallowest ancestor that needs to load, not strictly the shallowest ancestor with a loader (#14150)react-router - Propagate non-redirect Response values thrown from middleware to the error boundary on document/data requests (#14182)RSC
react-router - Provide isRouteErrorResponse utility in react-server environments (#14166)react-router - Handle meta and links Route Exports in RSC Data Mode (#14136)Full Changelog: v7.8.0...v7.8.1
Nothing published for this version
Nothing published for this version
⚠️ This is a breaking change if you have adopted the unstable_getContext prop
Date: 2025-08-07
loaderData valuesEver noticed the discrepancies in loader data values handed to you by the framework? Like, we call it loaderData in your component props, but then match.data in your matches? Yeah, us too - as well as some keen-eyed React Router users who raised this in a proposal. We've added new loaderData fields alongside existing data fields in a few lingering spots to align with the loaderData naming used in the new Route.* APIs.
The biggest set of changes in 7.8.0 are to the unstable_middleware API's as we move closer to stabilizing them. If you've adopted the middleware APIs for early testing, please read the middleware changes below carefully. We hope to stabilize these soon so please let us know of any feedback you have on the API's in their current state!
react-router - Add nonce prop to Links & PrefetchPageLinks (#14048)react-router - Add loaderData arguments/properties alongside existing data arguments/properties to provide consistency and clarity between loaderData and actionData across the board (#14047)
Route.MetaArgs, Route.MetaMatch, MetaArgs, MetaMatch, Route.ComponentProps.matches, UIMatch@deprecated warnings have been added to the existing data properties to point users to new loaderData properties, in preparation for removing the data properties in a future major releasereact-router - Prevent "Did not find corresponding fetcher result" console error when navigating during a fetcher.submit revalidation (#14114)
react-router - Switch Lazy Route Discovery manifest URL generation to use a standalone URLSearchParams instance instead of URL.searchParams to avoid a major performance bottleneck in Chrome (#14084)
react-router - Adjust internal RSC usage of React.use to avoid Webpack compilation errors when using React 18 (#14113)
react-router - Remove dependency on @types/node in TypeScript declaration files (#14059)
react-router - Fix types for UIMatch to reflect that the loaderData/data properties may be undefined (#12206)
When an ErrorBoundary is being rendered, not all active matches will have loader data available, since it may have been their loader that threw to trigger the boundary
The UIMatch.data type was not correctly handing this and would always reflect the presence of data, leading to the unexpected runtime errors when an ErrorBoundary was rendered
⚠️ This may cause some type errors to show up in your code for unguarded match.data accesses - you should properly guard for undefined values in those scenarios.
// app/root.tsx
export function loader() {
someFunctionThatThrows(); // ❌ Throws an Error
return { title: "My Title" };
}
export function Layout({ children }: { children: React.ReactNode }) {
let matches = useMatches();
let rootMatch = matches[0] as UIMatch<Awaited<ReturnType<typeof loader>>>;
// ^ rootMatch.data is currently incorrectly typed here, so TypeScript does
// not complain if you do the following which throws an error at runtime:
let { title } = rootMatch.data; // 💥
return <html>...</html>;
}
@react-router/dev - Fix rename without mkdir in Vite plugin (#14105)
⚠️ Unstable features are not recommended for production use
RSC
react-router - Fix Data Mode issue where routes that return false from shouldRevalidate would be replaced by an <Outlet /> (#14071)react-router - Proxy server action side-effect redirects from actions for document and callServer requests (#14131)Middleware
react-router - Change the unstable_getContext signature on RouterProvider, HydratedRouter, and unstable_RSCHydratedRouter so that it returns an unstable_RouterContextProvider instance instead of a Map used to construct the instance internally (#14097)
unstable_getContext propreact-router - Run client middleware on client navigations even if no loaders exist (#14106)
react-router - Convert internal middleware implementations to use the new unstable_generateMiddlewareResponse API (#14103)
react-router - Ensure resource route errors go through handleError w/middleware enabled (#14078)
react-router - Propagate returned Response from server middleware if next wasn't called (#14093)
react-router - Allow server middlewares to return data() values which will be converted into a Response (#14093, #14128)
react-router - Update middleware error handling so that the next function never throws and instead handles any middleware errors at the proper ErrorBoundary and returns the Response up through the ancestor next function (#14118)
next calls in try/catch you should be able to remove thosereact-router - Bubble client-side middleware errors prior to next to the appropriate ancestor error boundary (#14138)
react-router - When middleware is enabled, make the context parameter read-only (Readonly<unstable_RouterContextProvider>) so that TypeScript will not allow you to write arbitrary fields to it in loaders, actions, or middleware. (#14097)
react-router - Rename and alter the signature/functionality of the unstable_respond API in staticHandler.query/staticHandler.queryRoute (#14103)
This only impacts users using createStaticHandler() for manual data loading during non-Framework Mode SSR
The API has been renamed to unstable_generateMiddlewareResponse for clarity
The main functional change is that instead of running the loaders/actions before calling unstable_respond and handing you the result, we now pass a query/queryRoute function as a parameter and you execute the loaders/actions inside your callback, giving you full access to pre-processing and error handling
The query version of the API now has a signature of (query: (r: Request) => Promise<StaticHandlerContext | Response>) => Promise<Response>
The queryRoute version of the API now has a signature of (queryRoute: (r: Request) => Promise<Response>) => Promise<Response>
This allows for more advanced usages such as running logic before/after calling query and direct error handling of errors thrown from query
⚠️ This is a breaking change if you've adopted the staticHandler unstable_respond API
let response = await staticHandler.query(request, {
requestContext: new unstable_RouterContextProvider(),
async unstable_generateMiddlewareResponse(query) {
try {
// At this point we've run middleware top-down so we need to call the
// handlers and generate the Response to bubble back up the middleware
let result = await query(request);
if (isResponse(result)) {
return result; // Redirects, etc.
}
return await generateHtmlResponse(result);
} catch (error: unknown) {
return generateErrorResponse(error);
}
},
});
@react-router/{architect,cloudflare,express,node} - Change the getLoadContext signature (type GetLoadContextFunction) when future.unstable_middleware is enabled so that it returns an unstable_RouterContextProvider instance instead of a Map used to construct the instance internally (#14097)
type unstable_InitialContext exportgetLoadContext docs for more informationgetLoadContext functioncreate-react-routerreact-router@react-router/architect@react-router/cloudflare@react-router/dev@react-router/express@react-router/fs-routes@react-router/node@react-router/remix-config-routes-adapter@react-router/serveFull Changelog: v7.7.1...v7.8.0
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
@react-router/dev - Update to Prettier v3 for formatting when running react-router reveal --no-typescript
Date: 2025-07-24
@react-router/dev - Update to Prettier v3 for formatting when running react-router reveal --no-typescript (#14049)⚠️ Unstable features are not recommended for production use
react-router - RSC Data Mode: fix bug where routes with errors weren't forced to revalidate when shouldRevalidate returned false (#14026)react-router - RSC Data Mode: fix Matched leaf route at location "/..." does not have an element or Component warnings when error boundaries are rendered (#14021)Full Changelog: v7.7.0...v7.7.1
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →