Skip to content

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Feb 16, 2025

This PR contains the following updates:

Package Update Change
remix-run/react-router major 6.30.1 -> 7.9.5

Release Notes

remix-run/react-router (remix-run/react-router)

v7.9.5

Compare Source

Date: 2025-10-29

What's Changed
Instrumentation (unstable)

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.

Patch Changes
  • 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 Changes

⚠️ 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)

    • Framework Mode:
      • entry.server.tsx: export const unstable_instrumentations = [...]
      • entry.client.tsx: <HydratedRouter unstable_instrumentations={[...]} />
    • Data Mode
      • 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

v7.9.4

Compare Source

Date: 2025-10-08

What's Changed
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.

Patch Changes
  • @react-router/dev - Update valibot dependency to ^1.1.0 (#​14379)
  • @react-router/node - Validate format of incoming session ids in createFileSessionStorage (#​14426)
Unstable Changes

⚠️ 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

v7.9.3

Compare Source

Date: 2025-09-26

Patch Changes
  • 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)
    • This was logic we used to have in Remix v2 that got lost in the adoption of Single Fetch
    • This permits the actual CDN error to bubble to the ErrorBoundary instead of a generic "Unable to decode turbo-stream response" error

Full Changelog: v7.9.2...v7.9.3

v7.9.2

Compare Source

Date: 2025-09-24

What's Changed

This release contains a handful of bug fixes, but we think you'll be most excited about the new unstable stuff 😉.

RSC Framework Mode (unstable)

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.

Fetcher Reset (unstable)

This release also includes a new (long-requested) fetcher.unstable_reset() API to reset fetchers back to their initial idle state.

Patch Changes
  • 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)
    • You will need to set the <RoutesStub future={{ v8_middleware: true }} /> flag to enable the proper context type
  • react-router - Update Lazy Route Discovery manifest requests to use a singular comma-separated paths query param instead of repeated p query params (#​14321)
    • This is because Cloudflare has a hard limit of 100 URL search param key/value pairs when used as a key for caching purposes
    • If more that 100 paths were included, the cache key would be incomplete and could produce false-positive cache hits
  • 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 Changes

⚠️ 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

v7.9.1

Compare Source

Date: 2025-09-12

Patch Changes
  • Fix internal Future interface naming from middleware -> v8_middleware (#​14327)

Full Changelog: v7.9.0...v7.9.1

v7.9.0

Compare Source

Date: 2025-09-12

What's Changed
Stable Middleware and Context APIs

We have removed the unstable_ prefix from the following APIs and they are now considered stable and ready for production use:

Please see the Middleware Docs, the Middleware RFC, and the Client-side Context RFC for more information.

Minor Changes
  • Stabilize middleware and context APIs (#​14215)
Patch Changes
  • 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 Changes

⚠️ 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

v7.8.2

Compare Source

Date: 2025-08-22

Patch Changes
  • 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 Changes

⚠️ 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)
    • This is only needed as a Framework Mode flag because of the route modules and the getLoadContext type behavior change
    • In Data Mode, it's an opt-in feature because it's just a new property on a route object, so there's no behavior changes that necessitate a flag

RSC

  • react-router - Allow opting out of revalidation on server actions with hidden $SKIP_REVALIDATION input (#​14154)

Full Changelog: v7.8.1...v7.8.2

v7.8.1

Compare Source

Date: 2025-08-15

Patch Changes
  • 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 Changes

⚠️ 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

v7.8.0

Compare Source

Date: 2025-08-07

What's Changed
Consistently named loaderData values

Ever 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.

Improvements/fixes to the middleware APIs (unstable)

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!

Minor Changes
  • 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)
    • Updated types: 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 release
Patch Changes
  • react-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 Changes

⚠️ 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)

    • See the docs for more information
    • ⚠️ This is a breaking change if you have adopted the unstable_getContext prop
  • react-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)

    • See the error handling docs for more information
    • ⚠️ This changes existing functionality so if you are currently wrapping next calls in try/catch you should be able to remove those
  • react-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)

    • This also removes the type unstable_InitialContext export
    • See the middleware getLoadContext docs for more information
    • ⚠️ This is a breaking change if you have adopted middleware and are using a custom server with a getLoadContext function
Changes by Package

Full Changelog: v7.7.1...v7.8.0

v7.7.1

Compare Source

Date: 2025-07-24

Patch Changes
  • @react-router/dev - Update to Prettier v3 for formatting when running react-router reveal --no-typescript (#​14049)
Unstable Changes

⚠️ 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

v7.7.0

Compare Source

Date: 2025-07-16

What's Changed
Unstable RSC APIs

We're excited to introduce experimental support for RSC in Data Mode via the following new APIs:

For more information, check out the blog post and the RSC Docs.

Minor Changes
  • create-react-router - Add Deno as a supported and detectable package manager. Note that this detection will only work with Deno versions 2.0.5 and above. If you are using an older version version of Deno then you must specify the --package-manager CLI flag set to deno. (#​12327)
  • @react-router/remix-config-routes-adapter - Export DefineRouteFunction type alongside DefineRoutesFunction (#​13945)
Patch Changes
  • react-router - Handle InvalidCharacterError when validating cookie signature (#​13847)

  • react-router - Pass a copy of searchParams to the setSearchParams callback function to avoid mutations of the internal searchParams instance (#​12784)

    • This causes bugs if you mutate the current stateful searchParams when a navigation is blocked because the internal instance gets out of sync with useLocation().search
  • react-router - Support invalid Date in turbo-stream v2 fork (#​13684)

  • react-router - In Framework Mode, clear critical CSS in development after initial render (#​13872, #​13995)

  • react-router - Strip search parameters from patchRoutesOnNavigation path param for fetcher calls (#​13911)

  • react-router - Skip scroll restoration on useRevalidator() calls because they're not new locations (#​13671)

  • react-router - Support unencoded UTF-8 routes in prerender config with ssr set to false (#​13699)

  • react-router - Do not throw if the url hash is not a valid URI component (#​13247)

  • react-router - Remove Content-Length header from Single Fetch responses (#​13902)

  • react-router - Fix a regression in createRoutesStub introduced with the middleware feature (#​13946)

    • As part of that work we altered the signature to align with the new middleware APIs without making it backwards compatible with the prior AppLoadContext API

    • This permitted createRoutesStub to work if you were opting into middleware and the updated context typings, but broke createRoutesStub for users not yet opting into middleware

    • We've reverted this change and re-implemented it in such a way that both sets of users can leverage it

    • ⚠️ This may be a breaking bug for if you have adopted the unstable Middleware feature and are using createRoutesStub with the updated API.

      // If you have not opted into middleware, the old API should work again
      let context: AppLoadContext = {
        /*...*/
      };
      let Stub = createRoutesStub(routes, context);
      
      // If you have opted into middleware, you should now pass an instantiated
      // `unstable_routerContextProvider` instead of a `getContext` factory function.
      let context = new unstable_RouterContextProvider();
      context.set(SomeContext, someValue);
      let Stub = createRoutesStub(routes, context);
  • @react-router/dev - Update vite-node to ^3.2.2 to support Vite 7 (#​13781)

  • @react-router/dev - Properly handle https protocol in dev mode (#​13746)

  • @react-router/dev - Fix missing styles when Vite's build.cssCodeSplit option is disabled (#​13943)

  • @react-router/dev - Allow .mts and .mjs extensions for route config file (#​13931)

  • @react-router/dev - Fix prerender file locations when cwd differs from project root (#​13824)

  • @react-router/dev - Improve chunk error logging when a chunk cannot be found during the build (#​13799)

  • @react-router/dev - Fix incorrectly configured externalConditions which had enabled module condition for externals and broke builds with certain packages (like Emotion) (#​13871)

Unstable Changes

⚠️ Unstable features are not recommended for production use

Changes by Package

Full Changelog: v7.6.3...v7.7.0

v7.6.3

Compare Source

Date: 2025-06-27

Patch Changes
  • react-router - Do not serialize types for useRouteLoaderData<typeof clientLoader> (#​13752)

    • For types to distinguish a clientLoader from a serverLoader, you MUST annotate clientLoader args:

      //                                   👇 annotation required to skip serializing types
      export function clientLoader({}: Route.ClientLoaderArgs) {
        return { fn: () => "earth" };
      }
      
      function SomeComponent() {
        const data = useRouteLoaderData<typeof clientLoader>("routes/this-route");
        const planet = data?.fn() ?? "world";
        return <h1>Hello, {planet}!</h1>;
      }
  • @react-router/cloudflare - Remove tsup from peerDependencies (#​13757)

  • @react-router/dev - Add Vite 7 support (#​13748)

  • @react-router/dev - Skip package.json resolution checks when a custom entry.server.(j|t)sx file is provided (#​13744)

  • @react-router/dev - Add validation for a route's id not being 'root' (#​13792)

  • @react-router/fs-routes @react-router/remix-config-routes-adapter - Use replaceAll for normalizing windows file system slashes (#​13738)

  • @react-router/node - Remove old "install" package exports (#​13762)

Full Changelog: v7.6.2...v7.6.3

v7.6.2

Compare Source

Date: 2025-06-03

Patch Changes
  • create-react-router - Update tar-fs (#​13675)

  • react-router - (INTERNAL) Slight refactor of internal headers() function processing for use with RSC (#​13639)

  • react-router @react-router/dev - Avoid additional with-props chunk in Framework Mode by moving route module component prop logic from the Vite plugin to react-router (#​13650)

  • @react-router/dev - When future.unstable_viteEnvironmentApi is enabled and an absolute Vite base has been configured, ensure critical CSS is handled correctly during development (#​13598)

  • @react-router/dev - Update vite-node (#​13673)

  • @react-router/dev - Fix typegen for non-{.js,.jsx,.ts,.tsx} routes like .mdx (#​12453)

  • @react-router/dev - Fix href types for optional dynamic params (#​13725)

    7.6.1 introduced fixes for href when using optional static segments,
    but those fixes caused regressions with how optional dynamic params worked in 7.6.0:

    // 7.6.0
    href("/users/:id?"); // ✅
    href("/users/:id?", { id: 1 }); // ✅
    
    // 7.6.1
    href("/users/:id?"); // ❌
    href("/users/:id?", { id: 1 }); // ❌

    Now, optional static segments are expanded into different paths for href, but optional dynamic params are not.
    This way href can unambiguously refer to an exact URL path, all while keeping the number of path options to a minimum.

    // 7.6.2
    
    // path: /users/:id?/edit?
    href("
    //    ^ suggestions when cursor is here:
    //
    //    /users/:id?
    //    /users/:id?/edit

    Additionally, you can pass params from component props without needing to narrow them manually:

    declare const params: { id?: number };
    
    // 7.6.0
    href("/users/:id?", params);
    
    // 7.6.1
    href("/users/:id?", params); // ❌
    "id" in params ? href("/users/:id", params) : href("/users"); // works... but is annoying
    
    // 7.6.2
    href("/users/:id?", params); // restores behavior of 7.6.0

Full Changelog: v7.6.1...v7.6.2

v7.6.1

Compare Source

Date: 2025-05-25

Patch Changes
  • react-router - Partially revert optimization added in 7.1.4 to reduce calls to matchRoutes because it surfaced other issues (#​13562)

  • react-router - Update Route.MetaArgs to reflect that data can be potentially undefined (#​13563)

    • This is primarily for cases where a route loader threw an error to it's own ErrorBoundary, but it also arises in the case of a 404 which renders the root ErrorBoundary/meta but the root loader did not run because not routes matched
  • react-router - Avoid initial fetcher execution 404 error when Lazy Route Discovery is interrupted by a navigation (#​13564)

  • react-router - Properly href replaces splats * (#​13593)

    • href("/products/*", { "*": "/1/edit" }); // -> /products/1/edit
  • @react-router/architect - Update @architect/functions from ^5.2.0 to ^7.0.0 (#​13556)

  • @react-router/dev - Prevent typegen with route files that are outside the app/ directory (#​12996)

  • @react-router/dev - Add additional logging to build command output when cleaning assets from server build (#​13547)

  • @react-router/dev - Don't clean assets from server build when build.ssrEmitAssets has been enabled in Vite config (#​13547)

  • @react-router/dev - Fix typegen when same route is used at multiple paths (#​13574)

    • For example, routes/route.tsx is used at 4 different paths here:

      import { type RouteConfig, route } from "@&#8203;react-router/dev/routes";
      export default [
        route("base/:base", "routes/base.tsx", [
          route("home/:home", "routes/route.tsx", { id: "home" }),
          route("changelog/:changelog", "routes/route.tsx", { id: "changelog" }),
          route("splat/*", "routes/route.tsx", { id: "splat" }),
        ]),
        route("other/:other", "routes/route.tsx", { id: "other" }),
      ] satisfies RouteConfig;
    • Previously, typegen would arbitrarily pick one of these paths to be the "winner" and generate types for the route module based on that path

    • Now, typegen creates unions as necessary for alternate paths for the same route file

  • @react-router/dev - Better types for params (#​13543)

    • For example:

      // routes.ts
      import { type RouteConfig, route } from "@&#8203;react-router/dev/routes";
      
      export default [
        route("parent/:p", "routes/parent.tsx", [
          route("route/:r", "routes/route.tsx", [
            route("child1/:c1a/:c1b", "routes/child1.tsx"),
            route("child2/:c2a/:c2b", "routes/child2.tsx"),
          ]),
        ]),
      ] satisfies RouteConfig;
    • Previously, params for routes/route were calculated as { p: string, r: string }.

    • This incorrectly ignores params that could come from child routes

    • If visiting /parent/1/route/2/child1/3/4, the actual params passed to routes/route will have a type of { p: string, r: string, c1a: string, c1b: string }

    • Now, params are aware of child routes and autocompletion will include child params as optionals:

      params.|
      //     ^ cursor is here and you ask for autocompletion
      // p: string
      // r: string
      // c1a?: string
      // c1b?: string
      // c2a?: string
      // c2b?: string
    • You can also narrow the types for params as it is implemented as a normalized union of params for each page that includes routes/route:

      if (typeof params.c1a === 'string') {
        params.|
        //     ^ cursor is here and you ask for autocompletion
        // p: string
        // r: string
        // c1a: string
        // c1b: string
      }
  • @react-router/dev - Fix href for optional segments (#​13595)

    • Type generation now expands paths with optionals into their corresponding non-optional paths

    • For example, the path /user/:id? gets expanded into /user and /user/:id to more closely model visitable URLs

    • href then uses these expanded (non-optional) paths to construct type-safe paths for your app:

      // original: /user/:id?
      // expanded: /user & /user/:id
      href("/user"); // ✅
      href("/user/:id", { id: 1 }); // ✅
    • This becomes even more important for static optional paths where there wasn't a good way to indicate whether the optional should be included in the resulting path:

      // original: /products/:id/detail?
      
      // before
      href("/products/:id/detail?"); // ❌ How can we tell `href` to include or omit `detail?` segment with a complex API?
      
      // now
      // expanded: /products/:id & /products/:id/detail
      href("/product/:id"); // ✅
      href("/product/:id/detail"); // ✅
Unstable Changes

⚠️ Unstable features are not recommended for production use

  • @react-router/dev - Renamed internal react-router/route-module export to react-router/internal (#​13543)
  • @react-router/dev - Removed Info export from generated +types/* files (#​13543)
  • @react-router/dev - Normalize dirent entry path across node versions when generating SRI manifest (#​13591)

Full Changelog: v7.6.0...v7.6.1

v7.6.0

Compare Source

Date: 2025-05-08

What's Changed
routeDiscovery Config Option

We've added a new config option in 7.6.0 which grants you more control over the Lazy Route Discovery feature. You can now configure the /__manifest path if you're running multiple RR applications on the same server, or you can also disable the feature entirely if your application is small enough and the feature isn't necessary.

// react-router.config.ts

export default {
  // You can modify the manifest path used:
  routeDiscovery: { mode: "lazy", manifestPath: "/custom-manifest" }

  // Or you can disable this feature entirely and include all routes in the
  // manifest on initial document load:
  routeDiscovery: { mode: "initial" }

  // If you don't specify anything, the default config is as follows, which enables
  // Lazy Route Discovery and makes manifest requests to the `/__manifest` path:
  // routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" }
} satisfies Config;
Automatic Types for Future Flags

Some future flags alter the way types should work in React Router. Previously, you had to remember to manually opt-in to the new types. For example, for future.unstable_middleware:

// react-router.config.ts

// Step 1: Enable middleware
export default {
  future: {
    unstable_middleware: true,
  },
};

// Step 2: Enable middleware types
declare module "react-router" {
  interface Future {
    unstable_middleware: true; // 👈 Enable middleware types
  }
}

It was up to you to keep the runtime future flags synced with the types for those flags. This was confusing and error-prone.

Now, React Router will automatically enable types for future flags. That means you only need to specify the runtime future flag:

// react-router.config.ts

// Step 1: Enable middleware
export default {
  future: {
    unstable_middleware: true,
  },
};

// No step 2! That's it!

Behind the scenes, React Router will generate the corresponding declare module into .react-router/types. Currently this is done in .react-router/types/+register.ts but this is an implementation detail that may change in the future.

Minor Changes
  • react-router - Added a new routeDiscovery option in react-router.config.ts to configure Lazy Route Discovery behavior (#​13451)

  • react-router -


Configuration

📅 Schedule: Branch creation - Between 12:00 AM and 03:59 AM, only on Monday ( * 0-3 * * 1 ) (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 2 times, most recently from f5f3ea7 to a4efe37 Compare February 18, 2025 21:42
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from a4efe37 to ecf17d5 Compare March 6, 2025 22:37
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 2 times, most recently from 2339790 to dc7e1be Compare March 22, 2025 10:44
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 2 times, most recently from 6a1e905 to a732bb8 Compare April 4, 2025 18:59
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 3 times, most recently from 07d7311 to 0a69083 Compare April 24, 2025 17:16
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 0a69083 to e9aca10 Compare April 28, 2025 23:59
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from e9aca10 to f12808a Compare May 8, 2025 19:13
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from f12808a to 55e43c9 Compare May 25, 2025 15:04
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 55e43c9 to 42c6b2f Compare June 2, 2025 07:54
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 2 times, most recently from adb8d44 to 599289f Compare June 27, 2025 18:44
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 599289f to eaecb07 Compare July 16, 2025 19:34
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from eaecb07 to 5e23db0 Compare July 24, 2025 23:13
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 5e23db0 to 6a1ae19 Compare August 7, 2025 21:33
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 2 times, most recently from 543a974 to 0f24534 Compare August 22, 2025 19:08
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 0f24534 to e34701c Compare September 12, 2025 21:06
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch 2 times, most recently from 714f67f to 97fb1ee Compare September 26, 2025 20:32
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 97fb1ee to 7251ffa Compare October 8, 2025 18:40
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 7251ffa to 8d38f2c Compare October 21, 2025 10:10
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from 8d38f2c to bf0a303 Compare October 29, 2025 17:58
@renovate renovate bot force-pushed the renovate/major-react-router-monorepo branch from bf0a303 to 22d7c4b Compare November 10, 2025 18:47
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