React Router Release Notes

Last updated: Dec 4, 2025

  • Dec 4, 2025
    • Parsed from source:
      Dec 4, 2025
    • Detected by Releasebot:
      Dec 9, 2025

    React Router by Remix

    v7.10.1

    Patch Changes

    • 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 (#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

    Original source Report a problem
  • Dec 2, 2025
    • Parsed from source:
      Dec 2, 2025
    • Detected by Releasebot:
      Dec 9, 2025

    React Router by Remix

    v7.10.0

    New release stabilizes several unstable APIs into stable flags like future.v8_splitRouteModules and future.v8_viteEnvironmentApi, plus fetcher.reset and data strategy APIs. Includes breaking changes and multiple patch fixes for React Router and dev tooling.

    What's Changed

    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!

    • Stabilized future.v8_splitRouteModules
    • Stabilized future.v8_splitRouteModules
    • The 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.
    • Stabilized future.v8_viteEnvironmentApi
    • Stabilized future.v8_viteEnvironmentApi
    • The 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.
    • Stabilized fetcher.reset()
    • Stabilized fetcher.reset()
    • The existing fetcher.unstable_reset() API has been stabilized as fetcher.reset().
    • Stabilized DataStrategyMatch.shouldCallHandler()
    • Stabilized 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.

    Minor Changes

    • react-router - Stabilize fetcher.reset() (#14545)
      ⚠️ This is a breaking change if you have begun using fetcher.unstable_reset() - please update your code to use fetcher.reset()
    • react-router - Stabilize the dataStrategy match.shouldCallHandler() / match.shouldRevalidateArgs APIs (#14592)
      The match.shouldLoad API is now marked deprecated in favor of these more powerful alternatives
      ⚠️ This is a breaking change if you have begun using match.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)
      ⚠️ This is a breaking change if you have begun using future.unstable_splitRouteModules - please update your react-router.config.ts
    • @react-router/dev - Stabilize future.v8_viteEnvironmentApi, replacing future.unstable_viteEnvironmentApi (#14595)
      ⚠️ This is a breaking change if you have begun using future.unstable_viteEnvironmentApi - please update your react-router.config.ts

    Patch Changes

    • react-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)
      If your shouldRevalidate function relied on that parameter, you may have seen unintended revalidations
    • react-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 Changes

    ⚠️ 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)
      Please see the docs for more information
      Framework Mode + Data Mode:
      ■ /
      ■ When left unset (current default behavior)
      ■ Router state updates are wrapped in React.startTransition
      ■ ⚠️ This can lead to buggy behaviors if you are wrapping your own navigations/fetchers in React.startTransition
      ■ You should set the flag to true if you run into this scenario to get the enhanced useOptimistic behavior (requires React 19)
      ■ When set to true
      ■ Router state updates remain wrapped in React.startTransition (as they are without the flag)
      ■ Link / Form navigations will be wrapped in React.startTransition
      ■ You can drop down to useNavigate / useSubmit if you wish to opt out of this outer React.startTransition call for the navigation
      ■ A subset of router state info will be surfaced to the UI during navigations via React.useOptimistic (i.e., useNavigation(), useFetchers(), etc.)
      ■ ⚠️ This is a React 19 API so you must also be React 19 to opt into this flag for Framework/Data Mode
      ■ When set to false
      ■ The router will not leverage React.startTransition or React.useOptimistic on any navigations or state changes

    Minor Changes

    • react-router - Stabilize fetcher.reset() (#14545)
      ⚠️ This is a breaking change if you have begun using fetcher.unstable_reset() - please update your code to use fetcher.reset()
    • react-router - Stabilize the dataStrategy match.shouldCallHandler() / match.shouldRevalidateArgs APIs (#14592)
      The match.shouldLoad API is now marked deprecated in favor of these more powerful alternatives
      ⚠️ This is a breaking change if you have begun using match.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)
      ⚠️ This is a breaking change if you have begun using future.unstable_splitRouteModules - please update your react-router.config.ts
    • @react-router/dev - Stabilize future.v8_viteEnvironmentApi, replacing future.unstable_viteEnvironmentApi (#14595)
      ⚠️ This is a breaking change if you have begun using future.unstable_viteEnvironmentApi - please update your react-router.config.ts

    Patch Changes

    • react-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)
      If your shouldRevalidate function relied on that parameter, you may have seen unintended revalidations
    • react-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 Changes

    ⚠️ 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)
      Please see the docs for more information
      Framework Mode + Data Mode:
      ■ /
      ■ When left unset (current default behavior)
      ■ Router state updates are wrapped in React.startTransition
      ■ ⚠️ This can lead to buggy behaviors if you are wrapping your own navigations/fetchers in React.startTransition
      ■ You should set the flag to true if you run into this scenario to get the enhanced useOptimistic behavior (requires React 19)
      ■ When set to true
      ■ Router state updates remain wrapped in React.startTransition (as they are without the flag)
      ■ Link / Form navigations will be wrapped in React.startTransition
      ■ You can drop down to useNavigate / useSubmit if you wish to opt out of this outer React.startTransition call for the navigation
      ■ A subset of router state info will be surfaced to the UI during navigations via React.useOptimistic (i.e., useNavigation(), useFetchers(), etc.)
      ■ ⚠️ This is a React 19 API so you must also be React 19 to opt into this flag for Framework/Data Mode
      ■ When set to false
      ■ The router will not leverage React.startTransition or React.useOptimistic on any navigations or state changes

    Full Changelog

    Full Changelog: v7.9.6...v7.10.0

    Original source Report a problem

This is the end. You've seen all the release notes in this feed!

Related products