fix(deps): update react-router monorepo to v7.6.0 #144

Open
kjuulh wants to merge 1 commits from renovate/react-router-monorepo into main
Owner

This PR contains the following updates:

Package Type Update Change
react-router (source) dependencies minor 7.2.0 -> 7.6.0
react-router-dom (source) dependencies minor 7.2.0 -> 7.6.0

Release Notes

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

v7.6.0

Compare Source

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

    • By default, Lazy Route Discovery is enabled and makes manifest requests to the /__manifest path:
      • routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" }
    • 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" }
  • Add support for route component props in createRoutesStub. This allows you to unit test your route components using the props instead of the hooks: (#​13528)

    let RoutesStub = createRoutesStub([
      {
        path: "/",
        Component({ loaderData }) {
          let data = loaderData as { message: string };
          return <pre data-testid="data">Message: {data.message}</pre>;
        },
        loader() {
          return { message: "hello" };
        },
      },
    ]);
    
    render(<RoutesStub />);
    
    await waitFor(() => screen.findByText("Message: hello"));
    
Patch Changes
  • Fix react-router module augmentation for NodeNext (#​13498)

  • Don't bundle react-router in react-router/dom CJS export (#​13497)

  • Fix bug where a submitting fetcher would get stuck in a loading state if a revalidating loader redirected (#​12873)

  • Fix hydration error if a server loader returned undefined (#​13496)

  • Fix initial load 404 scenarios in data mode (#​13500)

  • Stabilize useRevalidator's revalidate function (#​13542)

  • Preserve status code if a clientAction throws a data() result in framework mode (#​13522)

  • Be defensive against leading double slashes in paths to avoid Invalid URL errors from the URL constructor (#​13510)

    • Note we do not sanitize/normalize these paths - we only detect them so we can avoid the error that would be thrown by new URL("//", window.location.origin)
  • Remove Navigator declaration for navigator.connection.saveData to avoid messing with any other types beyond saveData in userland (#​13512)

  • Fix handleError params values on .data requests for routes with a dynamic param as the last URL segment (#​13481)

  • Don't trigger an ErrorBoundary UI before the reload when we detect a manifest verison mismatch in Lazy Route Discovery (#​13480)

  • Inline turbo-stream@2.4.1 dependency and fix decoding ordering of Map/Set instances (#​13518)

  • Only render dev warnings in DEV mode (#​13461)

  • UNSTABLE: Fix a few bugs with error bubbling in middleware use-cases (#​13538)

  • Short circuit post-processing on aborted dataStrategy requests (#​13521)

    • This resolves non-user-facing console errors of the form Cannot read properties of undefined (reading 'result')

v7.5.3

Compare Source

Patch Changes
  • Fix bug where bubbled action errors would result in loaderData being cleared at the handling ErrorBoundary route (#​13476)
  • Handle redirects from clientLoader.hydrate initial load executions (#​13477)

v7.5.2

Compare Source

Patch Changes
  • Update Single Fetch to also handle the 204 redirects used in ?_data requests in Remix v2 (#​13364)

    • This allows applications to return a redirect on .data requests from outside the scope of React Router (i.e., an express/hono middleware)
    • ⚠️ Please note that doing so relies on implementation details that are subject to change without a SemVer major release
    • This is primarily done to ease upgrading to Single Fetch for existing Remix v2 applications, but the recommended way to handle this is redirecting from a route middleware
  • Adjust approach for Prerendering/SPA Mode via headers (#​13453)

v7.5.1

Compare Source

Patch Changes
  • Fix single fetch bug where no revalidation request would be made when navigating upwards to a reused parent route (#​13253)

  • When using the object-based route.lazy API, the HydrateFallback and hydrateFallbackElement properties are now skipped when lazy loading routes after hydration. (#​13376)

    If you move the code for these properties into a separate file, you can use this optimization to avoid downloading unused hydration code. For example:

    createBrowserRouter([
      {
        path: "/show/:showId",
        lazy: {
          loader: async () => (await import("./show.loader.js")).loader,
          Component: async () => (await import("./show.component.js")).Component,
          HydrateFallback: async () =>
            (await import("./show.hydrate-fallback.js")).HydrateFallback,
        },
      },
    ]);
    
  • Properly revalidate prerendered paths when param values change (#​13380)

  • UNSTABLE: Add a new unstable_runClientMiddleware argument to dataStrategy to enable middleware execution in custom dataStrategy implementations (#​13395)

  • UNSTABLE: Add better error messaging when getLoadContext is not updated to return a Map" (#​13242)

  • Do not automatically add null to staticHandler.query() context.loaderData if routes do not have loaders (#​13223)

    • This was a Remix v2 implementation detail inadvertently left in for React Router v7
    • Now that we allow returning undefined from loaders, our prior check of loaderData[routeId] !== undefined was no longer sufficient and was changed to a routeId in loaderData check - these null values can cause issues for this new check
    • ⚠️ This could be a "breaking bug fix" for you if you are doing manual SSR with createStaticHandler()/<StaticRouterProvider>, and using context.loaderData to control <RouterProvider> hydration behavior on the client
  • Fix prerendering when a loader returns a redirect (#​13365)

  • UNSTABLE: Update context type for LoaderFunctionArgs/ActionFunctionArgs when middleware is enabled (#​13381)

  • Add support for the new unstable_shouldCallHandler/unstable_shouldRevalidateArgs APIs in dataStrategy (#​13253)

v7.5.0

Compare Source

Minor Changes
  • Add granular object-based API for route.lazy to support lazy loading of individual route properties, for example: (#​13294)

    createBrowserRouter([
      {
        path: "/show/:showId",
        lazy: {
          loader: async () => (await import("./show.loader.js")).loader,
          action: async () => (await import("./show.action.js")).action,
          Component: async () => (await import("./show.component.js")).Component,
        },
      },
    ]);
    

    Breaking change for route.unstable_lazyMiddleware consumers

    The route.unstable_lazyMiddleware property is no longer supported. If you want to lazily load middleware, you must use the new object-based route.lazy API with route.lazy.unstable_middleware, for example:

    createBrowserRouter([
      {
        path: "/show/:showId",
        lazy: {
          unstable_middleware: async () =>
            (await import("./show.middleware.js")).middleware,
          // etc.
        },
      },
    ]);
    
Patch Changes
  • Introduce unstable_subResourceIntegrity future flag that enables generation of an importmap with integrity for the scripts that will be loaded by the browser. (#​13163)

v7.4.1

Compare Source

Patch Changes
  • Fix types on unstable_MiddlewareFunction to avoid type errors when a middleware doesn't return a value (#​13311)

  • Dedupe calls to route.lazy functions (#​13260)

  • Add support for route.unstable_lazyMiddleware function to allow lazy loading of middleware logic. (#​13210)

    Breaking change for unstable_middleware consumers

    The route.unstable_middleware property is no longer supported in the return value from route.lazy. If you want to lazily load middleware, you must use route.unstable_lazyMiddleware.

v7.4.0

Compare Source

Patch Changes
  • Fix root loader data on initial load redirects in SPA mode (#​13222)
  • Load ancestor pathless/index routes in lazy route discovery for upwards non-eager-discoery routing (#​13203)
  • Fix shouldRevalidate behavior for clientLoader-only routes in ssr:true apps (#​13221)
  • UNSTABLE: Fix RequestHandler loadContext parameter type when middleware is enabled (#​13204)
  • UNSTABLE: Update Route.unstable_MiddlewareFunction to have a return value of Response | undefined instead of Response | void becaue you should not return anything if you aren't returning the Response (#​13199)
  • UNSTABLE(BREAKING): If a middleware throws an error, ensure we only bubble the error itself via next() and are no longer leaking the MiddlewareError implementation detail (#​13180)

v7.3.0

Compare Source

Minor Changes
  • Add fetcherKey as a parameter to patchRoutesOnNavigation (#​13061)

    • In framework mode, Lazy Route Discovery will now detect manifest version mismatches after a new deploy
    • On navigations to undiscovered routes, this mismatch will trigger a document reload of the destination path
    • On fetcher calls to undiscovered routes, this mismatch will trigger a document reload of the current path
Patch Changes
  • Skip resource route flow in dev server in SPA mode (#​13113)

  • Support middleware on routes (unstable) (#​12941)

    Middleware is implemented behind a future.unstable_middleware flag. To enable, you must enable the flag and the types in your react-router-config.ts file:

    import type { Config } from "@&#8203;react-router/dev/config";
    import type { Future } from "react-router";
    
    declare module "react-router" {
      interface Future {
        unstable_middleware: true; // 👈 Enable middleware types
      }
    }
    
    export default {
      future: {
        unstable_middleware: true, // 👈 Enable middleware
      },
    } satisfies Config;
    

    ⚠️ Middleware is unstable and should not be adopted in production. There is at least one known de-optimization in route module loading for clientMiddleware that we will be addressing this before a stable release.

    ⚠️ Enabling middleware contains a breaking change to the context parameter passed to your loader/action functions - see below for more information.

    Once enabled, routes can define an array of middleware functions that will run sequentially before route handlers run. These functions accept the same parameters as loader/action plus an additional next parameter to run the remaining data pipeline. This allows middlewares to perform logic before and after handlers execute.

    // Framework mode
    export const unstable_middleware = [serverLogger, serverAuth]; // server
    export const unstable_clientMiddleware = [clientLogger]; // client
    
    // Library mode
    const routes = [
      {
        path: "/",
        // Middlewares are client-side for library mode SPA's
        unstable_middleware: [clientLogger, clientAuth],
        loader: rootLoader,
        Component: Root,
      },
    ];
    

    Here's a simple example of a client-side logging middleware that can be placed on the root route:

    const clientLogger: Route.unstable_ClientMiddlewareFunction = async (
      { request },
      next
    ) => {
      let start = performance.now();
    
      // Run the remaining middlewares and all route loaders
      await next();
    
      let duration = performance.now() - start;
      console.log(`Navigated to ${request.url} (${duration}ms)`);
    };
    

    Note that in the above example, the next/middleware functions don't return anything. This is by design as on the client there is no "response" to send over the network like there would be for middlewares running on the server. The data is all handled behind the scenes by the stateful router.

    For a server-side middleware, the next function will return the HTTP Response that React Router will be sending across the wire, thus giving you a chance to make changes as needed. You may throw a new response to short circuit and respond immediately, or you may return a new or altered response to override the default returned by next().

    const serverLogger: Route.unstable_MiddlewareFunction = async (
      { request, params, context },
      next
    ) => {
      let start = performance.now();
    
      // 👇 Grab the response here
      let res = await next();
    
      let duration = performance.now() - start;
      console.log(`Navigated to ${request.url} (${duration}ms)`);
    
      // 👇 And return it here (optional if you don't modify the response)
      return res;
    };
    

    You can throw a redirect from a middleware to short circuit any remaining processing:

    import { sessionContext } from "../context";
    const serverAuth: Route.unstable_MiddlewareFunction = (
      { request, params, context },
      next
    ) => {
      let session = context.get(sessionContext);
      let user = session.get("user");
      if (!user) {
        session.set("returnTo", request.url);
        throw redirect("/login", 302);
      }
    };
    

    Note that in cases like this where you don't need to do any post-processing you don't need to call the next function or return a Response.

    Here's another example of using a server middleware to detect 404s and check the CMS for a redirect:

    const redirects: Route.unstable_MiddlewareFunction = async ({
      request,
      next,
    }) => {
      // attempt to handle the request
      let res = await next();
    
      // if it's a 404, check the CMS for a redirect, do it last
      // because it's expensive
      if (res.status === 404) {
        let cmsRedirect = await checkCMSRedirects(request.url);
        if (cmsRedirect) {
          throw redirect(cmsRedirect, 302);
        }
      }
    
      return res;
    };
    

    context parameter

    When middleware is enabled, your application will use a different type of context parameter in your loaders and actions to provide better type safety. Instead of AppLoadContext, context will now be an instance of ContextProvider that you can use with type-safe contexts (similar to React.createContext):

    import { unstable_createContext } from "react-router";
    import { Route } from "./+types/root";
    import type { Session } from "./sessions.server";
    import { getSession } from "./sessions.server";
    
    let sessionContext = unstable_createContext<Session>();
    
    const sessionMiddleware: Route.unstable_MiddlewareFunction = ({
      context,
      request,
    }) => {
      let session = await getSession(request);
      context.set(sessionContext, session);
      //                          ^ must be of type Session
    };
    
    // ... then in some downstream middleware
    const loggerMiddleware: Route.unstable_MiddlewareFunction = ({
      context,
      request,
    }) => {
      let session = context.get(sessionContext);
      //  ^ typeof Session
      console.log(session.get("userId"), request.method, request.url);
    };
    
    // ... or some downstream loader
    export function loader({ context }: Route.LoaderArgs) {
      let session = context.get(sessionContext);
      let profile = await getProfile(session.get("userId"));
      return { profile };
    }
    

    If you are using a custom server with a getLoadContext function, the return value for initial context values passed from the server adapter layer is no longer an object and should now return an unstable_InitialContext (Map<RouterContext, unknown>):

    let adapterContext = unstable_createContext<MyAdapterContext>();
    
    function getLoadContext(req, res): unstable_InitialContext {
      let map = new Map();
      map.set(adapterContext, getAdapterContext(req));
      return map;
    }
    
  • Fix types for loaderData and actionData that contained Records (#​13139)

    UNSTABLE(BREAKING):

    unstable_SerializesTo added a way to register custom serialization types in Single Fetch for other library and framework authors like Apollo.
    It was implemented with branded type whose branded property that was made optional so that casting arbitrary values was easy:

    // without the brand being marked as optional
    let x1 = 42 as unknown as unstable_SerializesTo<number>;
    //          ^^^^^^^^^^
    
    // with the brand being marked as optional
    let x2 = 42 as unstable_SerializesTo<number>;
    

    However, this broke type inference in loaderData and actionData for any Record types as those would now (incorrectly) match unstable_SerializesTo.
    This affected all users, not just those that depended on unstable_SerializesTo.
    To fix this, the branded property of unstable_SerializesTo is marked as required instead of optional.

    For library and framework authors using unstable_SerializesTo, you may need to add as unknown casts before casting to unstable_SerializesTo.

  • [REMOVE] Remove middleware depth logic and always call middlware for all matches (#​13172)

  • Fix single fetch _root.data requests when a basename is used (#​12898)

  • Add context support to client side data routers (unstable) (#​12941)

    Your application loader and action functions on the client will now receive a context parameter. This is an instance of unstable_RouterContextProvider that you use with type-safe contexts (similar to React.createContext) and is most useful with the corresponding middleware/clientMiddleware API's:

    import { unstable_createContext } from "react-router";
    
    type User = {
      /*...*/
    };
    
    let userContext = unstable_createContext<User>();
    
    function sessionMiddleware({ context }) {
      let user = await getUser();
      context.set(userContext, user);
    }
    
    // ... then in some downstream loader
    function loader({ context }) {
      let user = context.get(userContext);
      let profile = await getProfile(user.id);
      return { profile };
    }
    

    Similar to server-side requests, a fresh context will be created per navigation (or fetcher call). If you have initial data you'd like to populate in the context for every request, you can provide an unstable_getContext function at the root of your app:

    • Library mode - createBrowserRouter(routes, { unstable_getContext })
    • Framework mode - <HydratedRouter unstable_getContext>

    This function should return an value of type unstable_InitialContext which is a Map<unstable_RouterContext, unknown> of context's and initial values:

    const loggerContext = unstable_createContext<(...args: unknown[]) => void>();
    
    function logger(...args: unknown[]) {
      console.log(new Date.toISOString(), ...args);
    }
    
    function unstable_getContext() {
      let map = new Map();
      map.set(loggerContext, logger);
      return map;
    }
    
remix-run/react-router (react-router-dom)

v7.6.0

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.6.0

v7.5.3

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.5.3

v7.5.2

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.5.2

v7.5.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.5.1

v7.5.0

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.5.0

v7.4.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.4.1

v7.4.0

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.4.0

v7.3.0

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@7.3.0

Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

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


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

This PR has been generated by Renovate Bot.

This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [react-router](https://github.com/remix-run/react-router) ([source](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)) | dependencies | minor | [`7.2.0` -> `7.6.0`](https://renovatebot.com/diffs/npm/react-router/7.2.0/7.6.0) | | [react-router-dom](https://github.com/remix-run/react-router) ([source](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom)) | dependencies | minor | [`7.2.0` -> `7.6.0`](https://renovatebot.com/diffs/npm/react-router-dom/7.2.0/7.6.0) | --- ### Release Notes <details> <summary>remix-run/react-router (react-router)</summary> ### [`v7.6.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#760) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.5.3...react-router@7.6.0) ##### Minor Changes - Added a new `react-router.config.ts` `routeDiscovery` option to configure Lazy Route Discovery behavior. ([#&#8203;13451](https://github.com/remix-run/react-router/pull/13451)) - By default, Lazy Route Discovery is enabled and makes manifest requests to the `/__manifest` path: - `routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" }` - 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" }` - Add support for route component props in `createRoutesStub`. This allows you to unit test your route components using the props instead of the hooks: ([#&#8203;13528](https://github.com/remix-run/react-router/pull/13528)) ```tsx let RoutesStub = createRoutesStub([ { path: "/", Component({ loaderData }) { let data = loaderData as { message: string }; return <pre data-testid="data">Message: {data.message}</pre>; }, loader() { return { message: "hello" }; }, }, ]); render(<RoutesStub />); await waitFor(() => screen.findByText("Message: hello")); ``` ##### Patch Changes - Fix `react-router` module augmentation for `NodeNext` ([#&#8203;13498](https://github.com/remix-run/react-router/pull/13498)) - Don't bundle `react-router` in `react-router/dom` CJS export ([#&#8203;13497](https://github.com/remix-run/react-router/pull/13497)) - Fix bug where a submitting `fetcher` would get stuck in a `loading` state if a revalidating `loader` redirected ([#&#8203;12873](https://github.com/remix-run/react-router/pull/12873)) - Fix hydration error if a server `loader` returned `undefined` ([#&#8203;13496](https://github.com/remix-run/react-router/pull/13496)) - Fix initial load 404 scenarios in data mode ([#&#8203;13500](https://github.com/remix-run/react-router/pull/13500)) - Stabilize `useRevalidator`'s `revalidate` function ([#&#8203;13542](https://github.com/remix-run/react-router/pull/13542)) - Preserve status code if a `clientAction` throws a `data()` result in framework mode ([#&#8203;13522](https://github.com/remix-run/react-router/pull/13522)) - Be defensive against leading double slashes in paths to avoid `Invalid URL` errors from the URL constructor ([#&#8203;13510](https://github.com/remix-run/react-router/pull/13510)) - Note we do not sanitize/normalize these paths - we only detect them so we can avoid the error that would be thrown by `new URL("//", window.location.origin)` - Remove `Navigator` declaration for `navigator.connection.saveData` to avoid messing with any other types beyond `saveData` in userland ([#&#8203;13512](https://github.com/remix-run/react-router/pull/13512)) - Fix `handleError` `params` values on `.data` requests for routes with a dynamic param as the last URL segment ([#&#8203;13481](https://github.com/remix-run/react-router/pull/13481)) - Don't trigger an `ErrorBoundary` UI before the reload when we detect a manifest verison mismatch in Lazy Route Discovery ([#&#8203;13480](https://github.com/remix-run/react-router/pull/13480)) - Inline `turbo-stream@2.4.1` dependency and fix decoding ordering of Map/Set instances ([#&#8203;13518](https://github.com/remix-run/react-router/pull/13518)) - Only render dev warnings in DEV mode ([#&#8203;13461](https://github.com/remix-run/react-router/pull/13461)) - UNSTABLE: Fix a few bugs with error bubbling in middleware use-cases ([#&#8203;13538](https://github.com/remix-run/react-router/pull/13538)) - Short circuit post-processing on aborted `dataStrategy` requests ([#&#8203;13521](https://github.com/remix-run/react-router/pull/13521)) - This resolves non-user-facing console errors of the form `Cannot read properties of undefined (reading 'result')` ### [`v7.5.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#753) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.5.2...react-router@7.5.3) ##### Patch Changes - Fix bug where bubbled action errors would result in `loaderData` being cleared at the handling `ErrorBoundary` route ([#&#8203;13476](https://github.com/remix-run/react-router/pull/13476)) - Handle redirects from `clientLoader.hydrate` initial load executions ([#&#8203;13477](https://github.com/remix-run/react-router/pull/13477)) ### [`v7.5.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#752) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.5.1...react-router@7.5.2) ##### Patch Changes - Update Single Fetch to also handle the 204 redirects used in `?_data` requests in Remix v2 ([#&#8203;13364](https://github.com/remix-run/react-router/pull/13364)) - This allows applications to return a redirect on `.data` requests from outside the scope of React Router (i.e., an `express`/`hono` middleware) - ⚠️ Please note that doing so relies on implementation details that are subject to change without a SemVer major release - This is primarily done to ease upgrading to Single Fetch for existing Remix v2 applications, but the recommended way to handle this is redirecting from a route middleware - Adjust approach for Prerendering/SPA Mode via headers ([#&#8203;13453](https://github.com/remix-run/react-router/pull/13453)) ### [`v7.5.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#751) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.5.0...react-router@7.5.1) ##### Patch Changes - Fix single fetch bug where no revalidation request would be made when navigating upwards to a reused parent route ([#&#8203;13253](https://github.com/remix-run/react-router/pull/13253)) - When using the object-based `route.lazy` API, the `HydrateFallback` and `hydrateFallbackElement` properties are now skipped when lazy loading routes after hydration. ([#&#8203;13376](https://github.com/remix-run/react-router/pull/13376)) If you move the code for these properties into a separate file, you can use this optimization to avoid downloading unused hydration code. For example: ```ts createBrowserRouter([ { path: "/show/:showId", lazy: { loader: async () => (await import("./show.loader.js")).loader, Component: async () => (await import("./show.component.js")).Component, HydrateFallback: async () => (await import("./show.hydrate-fallback.js")).HydrateFallback, }, }, ]); ``` - Properly revalidate prerendered paths when param values change ([#&#8203;13380](https://github.com/remix-run/react-router/pull/13380)) - UNSTABLE: Add a new `unstable_runClientMiddleware` argument to `dataStrategy` to enable middleware execution in custom `dataStrategy` implementations ([#&#8203;13395](https://github.com/remix-run/react-router/pull/13395)) - UNSTABLE: Add better error messaging when `getLoadContext` is not updated to return a `Map`" ([#&#8203;13242](https://github.com/remix-run/react-router/pull/13242)) - Do not automatically add `null` to `staticHandler.query()` `context.loaderData` if routes do not have loaders ([#&#8203;13223](https://github.com/remix-run/react-router/pull/13223)) - This was a Remix v2 implementation detail inadvertently left in for React Router v7 - Now that we allow returning `undefined` from loaders, our prior check of `loaderData[routeId] !== undefined` was no longer sufficient and was changed to a `routeId in loaderData` check - these `null` values can cause issues for this new check - ⚠️ This could be a "breaking bug fix" for you if you are doing manual SSR with `createStaticHandler()`/`<StaticRouterProvider>`, and using `context.loaderData` to control `<RouterProvider>` hydration behavior on the client - Fix prerendering when a loader returns a redirect ([#&#8203;13365](https://github.com/remix-run/react-router/pull/13365)) - UNSTABLE: Update context type for `LoaderFunctionArgs`/`ActionFunctionArgs` when middleware is enabled ([#&#8203;13381](https://github.com/remix-run/react-router/pull/13381)) - Add support for the new `unstable_shouldCallHandler`/`unstable_shouldRevalidateArgs` APIs in `dataStrategy` ([#&#8203;13253](https://github.com/remix-run/react-router/pull/13253)) ### [`v7.5.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#750) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.4.1...react-router@7.5.0) ##### Minor Changes - Add granular object-based API for `route.lazy` to support lazy loading of individual route properties, for example: ([#&#8203;13294](https://github.com/remix-run/react-router/pull/13294)) ```ts createBrowserRouter([ { path: "/show/:showId", lazy: { loader: async () => (await import("./show.loader.js")).loader, action: async () => (await import("./show.action.js")).action, Component: async () => (await import("./show.component.js")).Component, }, }, ]); ``` **Breaking change for `route.unstable_lazyMiddleware` consumers** The `route.unstable_lazyMiddleware` property is no longer supported. If you want to lazily load middleware, you must use the new object-based `route.lazy` API with `route.lazy.unstable_middleware`, for example: ```ts createBrowserRouter([ { path: "/show/:showId", lazy: { unstable_middleware: async () => (await import("./show.middleware.js")).middleware, // etc. }, }, ]); ``` ##### Patch Changes - Introduce `unstable_subResourceIntegrity` future flag that enables generation of an importmap with integrity for the scripts that will be loaded by the browser. ([#&#8203;13163](https://github.com/remix-run/react-router/pull/13163)) ### [`v7.4.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#741) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.4.0...react-router@7.4.1) ##### Patch Changes - Fix types on `unstable_MiddlewareFunction` to avoid type errors when a middleware doesn't return a value ([#&#8203;13311](https://github.com/remix-run/react-router/pull/13311)) - Dedupe calls to `route.lazy` functions ([#&#8203;13260](https://github.com/remix-run/react-router/pull/13260)) - Add support for `route.unstable_lazyMiddleware` function to allow lazy loading of middleware logic. ([#&#8203;13210](https://github.com/remix-run/react-router/pull/13210)) **Breaking change for `unstable_middleware` consumers** The `route.unstable_middleware` property is no longer supported in the return value from `route.lazy`. If you want to lazily load middleware, you must use `route.unstable_lazyMiddleware`. ### [`v7.4.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#740) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.3.0...react-router@7.4.0) ##### Patch Changes - Fix root loader data on initial load redirects in SPA mode ([#&#8203;13222](https://github.com/remix-run/react-router/pull/13222)) - Load ancestor pathless/index routes in lazy route discovery for upwards non-eager-discoery routing ([#&#8203;13203](https://github.com/remix-run/react-router/pull/13203)) - Fix `shouldRevalidate` behavior for `clientLoader`-only routes in `ssr:true` apps ([#&#8203;13221](https://github.com/remix-run/react-router/pull/13221)) - UNSTABLE: Fix `RequestHandler` `loadContext` parameter type when middleware is enabled ([#&#8203;13204](https://github.com/remix-run/react-router/pull/13204)) - UNSTABLE: Update `Route.unstable_MiddlewareFunction` to have a return value of `Response | undefined` instead of `Response | void` becaue you should not return anything if you aren't returning the `Response` ([#&#8203;13199](https://github.com/remix-run/react-router/pull/13199)) - UNSTABLE(BREAKING): If a middleware throws an error, ensure we only bubble the error itself via `next()` and are no longer leaking the `MiddlewareError` implementation detail ([#&#8203;13180](https://github.com/remix-run/react-router/pull/13180)) ### [`v7.3.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#730) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@7.2.0...react-router@7.3.0) ##### Minor Changes - Add `fetcherKey` as a parameter to `patchRoutesOnNavigation` ([#&#8203;13061](https://github.com/remix-run/react-router/pull/13061)) - In framework mode, Lazy Route Discovery will now detect manifest version mismatches after a new deploy - On navigations to undiscovered routes, this mismatch will trigger a document reload of the destination path - On `fetcher` calls to undiscovered routes, this mismatch will trigger a document reload of the current path ##### Patch Changes - Skip resource route flow in dev server in SPA mode ([#&#8203;13113](https://github.com/remix-run/react-router/pull/13113)) - Support middleware on routes (unstable) ([#&#8203;12941](https://github.com/remix-run/react-router/pull/12941)) Middleware is implemented behind a `future.unstable_middleware` flag. To enable, you must enable the flag and the types in your `react-router-config.ts` file: ```ts import type { Config } from "@&#8203;react-router/dev/config"; import type { Future } from "react-router"; declare module "react-router" { interface Future { unstable_middleware: true; // 👈 Enable middleware types } } export default { future: { unstable_middleware: true, // 👈 Enable middleware }, } satisfies Config; ``` ⚠️ Middleware is unstable and should not be adopted in production. There is at least one known de-optimization in route module loading for `clientMiddleware` that we will be addressing this before a stable release. ⚠️ Enabling middleware contains a breaking change to the `context` parameter passed to your `loader`/`action` functions - see below for more information. Once enabled, routes can define an array of middleware functions that will run sequentially before route handlers run. These functions accept the same parameters as `loader`/`action` plus an additional `next` parameter to run the remaining data pipeline. This allows middlewares to perform logic before and after handlers execute. ```tsx // Framework mode export const unstable_middleware = [serverLogger, serverAuth]; // server export const unstable_clientMiddleware = [clientLogger]; // client // Library mode const routes = [ { path: "/", // Middlewares are client-side for library mode SPA's unstable_middleware: [clientLogger, clientAuth], loader: rootLoader, Component: Root, }, ]; ``` Here's a simple example of a client-side logging middleware that can be placed on the root route: ```tsx const clientLogger: Route.unstable_ClientMiddlewareFunction = async ( { request }, next ) => { let start = performance.now(); // Run the remaining middlewares and all route loaders await next(); let duration = performance.now() - start; console.log(`Navigated to ${request.url} (${duration}ms)`); }; ``` Note that in the above example, the `next`/`middleware` functions don't return anything. This is by design as on the client there is no "response" to send over the network like there would be for middlewares running on the server. The data is all handled behind the scenes by the stateful `router`. For a server-side middleware, the `next` function will return the HTTP `Response` that React Router will be sending across the wire, thus giving you a chance to make changes as needed. You may throw a new response to short circuit and respond immediately, or you may return a new or altered response to override the default returned by `next()`. ```tsx const serverLogger: Route.unstable_MiddlewareFunction = async ( { request, params, context }, next ) => { let start = performance.now(); // 👇 Grab the response here let res = await next(); let duration = performance.now() - start; console.log(`Navigated to ${request.url} (${duration}ms)`); // 👇 And return it here (optional if you don't modify the response) return res; }; ``` You can throw a `redirect` from a middleware to short circuit any remaining processing: ```tsx import { sessionContext } from "../context"; const serverAuth: Route.unstable_MiddlewareFunction = ( { request, params, context }, next ) => { let session = context.get(sessionContext); let user = session.get("user"); if (!user) { session.set("returnTo", request.url); throw redirect("/login", 302); } }; ``` *Note that in cases like this where you don't need to do any post-processing you don't need to call the `next` function or return a `Response`.* Here's another example of using a server middleware to detect 404s and check the CMS for a redirect: ```tsx const redirects: Route.unstable_MiddlewareFunction = async ({ request, next, }) => { // attempt to handle the request let res = await next(); // if it's a 404, check the CMS for a redirect, do it last // because it's expensive if (res.status === 404) { let cmsRedirect = await checkCMSRedirects(request.url); if (cmsRedirect) { throw redirect(cmsRedirect, 302); } } return res; }; ``` **`context` parameter** When middleware is enabled, your application will use a different type of `context` parameter in your loaders and actions to provide better type safety. Instead of `AppLoadContext`, `context` will now be an instance of `ContextProvider` that you can use with type-safe contexts (similar to `React.createContext`): ```ts import { unstable_createContext } from "react-router"; import { Route } from "./+types/root"; import type { Session } from "./sessions.server"; import { getSession } from "./sessions.server"; let sessionContext = unstable_createContext<Session>(); const sessionMiddleware: Route.unstable_MiddlewareFunction = ({ context, request, }) => { let session = await getSession(request); context.set(sessionContext, session); // ^ must be of type Session }; // ... then in some downstream middleware const loggerMiddleware: Route.unstable_MiddlewareFunction = ({ context, request, }) => { let session = context.get(sessionContext); // ^ typeof Session console.log(session.get("userId"), request.method, request.url); }; // ... or some downstream loader export function loader({ context }: Route.LoaderArgs) { let session = context.get(sessionContext); let profile = await getProfile(session.get("userId")); return { profile }; } ``` If you are using a custom server with a `getLoadContext` function, the return value for initial context values passed from the server adapter layer is no longer an object and should now return an `unstable_InitialContext` (`Map<RouterContext, unknown>`): ```ts let adapterContext = unstable_createContext<MyAdapterContext>(); function getLoadContext(req, res): unstable_InitialContext { let map = new Map(); map.set(adapterContext, getAdapterContext(req)); return map; } ``` - Fix types for loaderData and actionData that contained `Record`s ([#&#8203;13139](https://github.com/remix-run/react-router/pull/13139)) UNSTABLE(BREAKING): `unstable_SerializesTo` added a way to register custom serialization types in Single Fetch for other library and framework authors like Apollo. It was implemented with branded type whose branded property that was made optional so that casting arbitrary values was easy: ```ts // without the brand being marked as optional let x1 = 42 as unknown as unstable_SerializesTo<number>; // ^^^^^^^^^^ // with the brand being marked as optional let x2 = 42 as unstable_SerializesTo<number>; ``` However, this broke type inference in `loaderData` and `actionData` for any `Record` types as those would now (incorrectly) match `unstable_SerializesTo`. This affected all users, not just those that depended on `unstable_SerializesTo`. To fix this, the branded property of `unstable_SerializesTo` is marked as required instead of optional. For library and framework authors using `unstable_SerializesTo`, you may need to add `as unknown` casts before casting to `unstable_SerializesTo`. - \[REMOVE] Remove middleware depth logic and always call middlware for all matches ([#&#8203;13172](https://github.com/remix-run/react-router/pull/13172)) - Fix single fetch `_root.data` requests when a `basename` is used ([#&#8203;12898](https://github.com/remix-run/react-router/pull/12898)) - Add `context` support to client side data routers (unstable) ([#&#8203;12941](https://github.com/remix-run/react-router/pull/12941)) Your application `loader` and `action` functions on the client will now receive a `context` parameter. This is an instance of `unstable_RouterContextProvider` that you use with type-safe contexts (similar to `React.createContext`) and is most useful with the corresponding `middleware`/`clientMiddleware` API's: ```ts import { unstable_createContext } from "react-router"; type User = { /*...*/ }; let userContext = unstable_createContext<User>(); function sessionMiddleware({ context }) { let user = await getUser(); context.set(userContext, user); } // ... then in some downstream loader function loader({ context }) { let user = context.get(userContext); let profile = await getProfile(user.id); return { profile }; } ``` Similar to server-side requests, a fresh `context` will be created per navigation (or `fetcher` call). If you have initial data you'd like to populate in the context for every request, you can provide an `unstable_getContext` function at the root of your app: - Library mode - `createBrowserRouter(routes, { unstable_getContext })` - Framework mode - `<HydratedRouter unstable_getContext>` This function should return an value of type `unstable_InitialContext` which is a `Map<unstable_RouterContext, unknown>` of context's and initial values: ```ts const loggerContext = unstable_createContext<(...args: unknown[]) => void>(); function logger(...args: unknown[]) { console.log(new Date.toISOString(), ...args); } function unstable_getContext() { let map = new Map(); map.set(loggerContext, logger); return map; } ``` </details> <details> <summary>remix-run/react-router (react-router-dom)</summary> ### [`v7.6.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#760) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.5.3...react-router-dom@7.6.0) ##### Patch Changes - Updated dependencies: - `react-router@7.6.0` ### [`v7.5.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#753) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.5.2...react-router-dom@7.5.3) ##### Patch Changes - Updated dependencies: - `react-router@7.5.3` ### [`v7.5.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#752) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.5.1...react-router-dom@7.5.2) ##### Patch Changes - Updated dependencies: - `react-router@7.5.2` ### [`v7.5.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#751) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.5.0...react-router-dom@7.5.1) ##### Patch Changes - Updated dependencies: - `react-router@7.5.1` ### [`v7.5.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#750) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.4.1...react-router-dom@7.5.0) ##### Patch Changes - Updated dependencies: - `react-router@7.5.0` ### [`v7.4.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#741) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.4.0...react-router-dom@7.4.1) ##### Patch Changes - Updated dependencies: - `react-router@7.4.1` ### [`v7.4.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#740) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.3.0...react-router-dom@7.4.0) ##### Patch Changes - Updated dependencies: - `react-router@7.4.0` ### [`v7.3.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#730) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@7.2.0...react-router-dom@7.3.0) ##### Patch Changes - Updated dependencies: - `react-router@7.3.0` </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMTUuMiIsInVwZGF0ZWRJblZlciI6IjM5LjI2NC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
kjuulh added 1 commit 2025-03-26 00:31:17 +01:00
kjuulh force-pushed renovate/react-router-monorepo from 4a806a2395 to 99c6432dc3 2025-03-28 23:06:28 +01:00 Compare
kjuulh changed title from fix(deps): update react-router monorepo to v7.4.0 to fix(deps): update react-router monorepo to v7.4.1 2025-03-28 23:06:39 +01:00
kjuulh force-pushed renovate/react-router-monorepo from 99c6432dc3 to 4418e1917a 2025-04-05 02:01:46 +02:00 Compare
kjuulh changed title from fix(deps): update react-router monorepo to v7.4.1 to fix(deps): update react-router monorepo to v7.5.0 2025-04-05 02:01:57 +02:00
kjuulh force-pushed renovate/react-router-monorepo from 4418e1917a to 1cc6f68307 2025-04-18 02:02:28 +02:00 Compare
kjuulh changed title from fix(deps): update react-router monorepo to v7.5.0 to fix(deps): update react-router monorepo to v7.5.1 2025-04-18 02:02:39 +02:00
kjuulh force-pushed renovate/react-router-monorepo from 1cc6f68307 to 3f1d8eb808 2025-04-25 02:02:28 +02:00 Compare
kjuulh changed title from fix(deps): update react-router monorepo to v7.5.1 to fix(deps): update react-router monorepo to v7.5.2 2025-04-25 02:02:39 +02:00
kjuulh force-pushed renovate/react-router-monorepo from 3f1d8eb808 to 5f8adf001f 2025-04-29 02:02:18 +02:00 Compare
kjuulh changed title from fix(deps): update react-router monorepo to v7.5.2 to fix(deps): update react-router monorepo to v7.5.3 2025-04-29 02:02:30 +02:00
kjuulh force-pushed renovate/react-router-monorepo from 5f8adf001f to cb061776a0 2025-05-09 02:02:04 +02:00 Compare
kjuulh changed title from fix(deps): update react-router monorepo to v7.5.3 to fix(deps): update react-router monorepo to v7.6.0 2025-05-09 02:02:15 +02:00
This pull request can be merged automatically.
You are not authorized to merge this pull request.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin renovate/react-router-monorepo:renovate/react-router-monorepo
git checkout renovate/react-router-monorepo
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kjuulh/backstage#144
No description provided.