Skip to content

Releases: remix-run/react-router

v6.13.0

14 Jun 16:01
ed17fcd
Compare
Choose a tag to compare

What's Changed

6.13.0 is really a patch release in spirit but comes with a SemVer minor bump since we added a new future flag.

The tl;dr; is that 6.13.0 is the same as 6.12.0 bue we've moved the usage of React.startTransition behind an opt-in future.v7_startTransition future flag because we found that there are applications in the wild that are currently using Suspense in ways that are incompatible with React.startTransition.

Therefore, in 6.13.0 the default behavior will no longer leverage React.startTransition:

<BrowserRouter>
  <Routes>{/*...*/}</Routes>
</BrowserRouter>

<RouterProvider router={router} />

If you wish to enable React.startTransition, pass the future flag to your router component:

<BrowserRouter future={{ v7_startTransition: true }}>
  <Routes>{/*...*/}</Routes>
</BrowserRouter>

<RouterProvider router={router} future={{ v7_startTransition: true }}/>

We recommend folks adopt this flag sooner rather than later to be better compatible with React concurrent mode, but if you run into issues you can continue without the use of React.startTransition until v7. Issues usually boil down to creating net-new promises during the render cycle, so if you run into issues when opting into React.startTransition, you should either lift your promise creation out of the render cycle or put it behind a useMemo.

Minor Changes

  • Move React.startTransition usage behinds a future flag (#10596)

Patch Changes

  • Work around webpack/terser React.startTransition minification bug in production mode (#10588)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.12.1...react-router@6.13.0

v6.12.1

08 Jun 16:49
77d7182
Compare
Choose a tag to compare

Warning
Please use version 6.13.0 or later instead of 6.12.0/6.12.1. These versions suffered from some Webpack build/minification issues resulting failed builds or invalid minified code in your production bundles. See #10569 and #10579 for more details.

Patch Changes

  • Adjust feature detection of React.startTransition to fix webpack + react 17 compilation error (#10569)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.12.0...react-router@6.12.1

v6.12.0

06 Jun 18:29
6c0bbb1
Compare
Choose a tag to compare

Warning
Please use version 6.13.0 or later instead of 6.12.0/6.12.1. These versions suffered from some Webpack build/minification issues resulting failed builds or invalid minified code in your production bundles. See #10569 and #10579 for more details.

What's Changed

With 6.12.0 we've added better support for suspending components by wrapping the internal router state updates in React.startTransition. This means that, for example, if one of your components in a destination route suspends and you have not provided a Suspense boundary to show a fallback, React will delay the rendering of the new UI and show the old UI until that asynchronous operation resolves. This could be useful for waiting for things such as waiting for images or CSS files to load (and technically, yes, you could use it for data loading but we'd still recommend using loaders for that πŸ˜€). For a quick overview of this usage, check out Ryan's demo on Twitter.

Minor Changes

  • Wrap internal router state updates with React.startTransition (#10438)

Patch Changes

  • Allow fetcher revalidations to complete if submitting fetcher is deleted (#10535)
  • Re-throw DOMException (DataCloneError) when attempting to perform a PUSH navigation with non-serializable state. (#10427)
  • Ensure revalidations happen when hash is present (#10516)
  • Upgrade jest and jsdom (#10453)
  • Updated dependencies:

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.11.2...react-router@6.12.0

v6.11.2

17 May 15:34
0815c96
Compare
Choose a tag to compare

Patch Changes

  • Fix basename duplication in descendant <Routes> inside a <RouterProvider> (#10492)
  • Fix bug where initial data load would not kick off when hash is present (#10493)
  • Export SetURLSearchParams type (#10444)
  • Fix Remix HMR-driven error boundaries by properly reconstructing new routes and manifest in _internalSetRoutes (#10437)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.11.1...react-router@6.11.2

v6.11.1

03 May 20:36
db696c1
Compare
Choose a tag to compare

Patch Changes

  • Fix usage of Component API within descendant <Routes> (#10434)
  • Fix bug when calling useNavigate from <Routes> inside a <RouterProvider> (#10432)
  • Fix usage of <Navigate> in strict mode when using a data router (#10435)
  • Fix basename handling when navigating without a path (#10433)
  • "Same hash" navigations no longer re-run loaders to match browser behavior (i.e. /path#hash -> /path#hash) (#10408)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.11.0...react-router@6.11.1

v6.11.0

28 Apr 17:10
7ff51c0
Compare
Choose a tag to compare

What's Changed

Minor Changes

  • Enable basename support in useFetcher (#10336)
    • If you were previously working around this issue by manually prepending the basename then you will need to remove the manually prepended basename from your fetcher calls (fetcher.load('/basename/route') -> fetcher.load('/route'))
  • Updated dependencies:

Patch Changes

  • When using a RouterProvider, useNavigate/useSubmit/fetcher.submit are now stable across location changes, since we can handle relative routing via the @remix-run/router instance and get rid of our dependence on useLocation() (#10336)
    • When using BrowserRouter, these hooks remain unstable across location changes because they still rely on useLocation()
  • Fetchers should no longer revalidate on search params changes or routing to the same URL, and will only revalidate on action submissions or router.revalidate calls (#10344)
  • Fix inadvertent re-renders when using Component instead of element on a route definition (#10287)
  • Fail gracefully on <Link to="//"> and other invalid URL values (#10367)
  • Switched from useSyncExternalStore to useState for internal @remix-run/router router state syncing in <RouterProvider>. We found some subtle bugs where router state updates got propagated before other normal useState updates, which could lead to foot guns in useEffect calls. (#10377, #10409)
  • Log loader/action errors caught by the default error boundary to the console in dev for easier stack trace evaluation (#10286)
  • Fix bug preventing rendering of descendant <Routes> when RouterProvider errors existed (#10374)
  • Fix detection of useNavigate in the render cycle by setting the activeRef in a layout effect, allowing the navigate function to be passed to child components and called in a useEffect there (#10394)
  • Allow useRevalidator() to resolve a loader-driven error boundary scenario (#10369)
  • Enhance LoaderFunction/ActionFunction return type to prevent undefined from being a valid return value (#10267)
  • Ensure proper 404 error on fetcher.load call to a route without a loader (#10345)
  • Decouple AbortController usage between revalidating fetchers and the thing that triggered them such that the unmount/deletion of a revalidating fetcher doesn't impact the ongoing triggering navigation/revalidation (#10271)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.10.0...react-router@6.11.0

v6.10.0

29 Mar 20:15
a3927fe
Compare
Choose a tag to compare

What's Changed

We recently published a post over on the Remix Blog titled "Future Proofing Your Remix App" that goes through our strategy to ensure smooth upgrades for your Remix and React Router apps going forward. React Router 6.10.0 adds support for these flags (for data routers) which you can specify when you create your router:

const router = createBrowserRouter(routes, {
  future: {
    // specify future flags here
  },
});

You can also check out the docs here and here.

Minor Changes

  • The first future flag being introduced is future.v7_normalizeFormMethod which will normalize the exposed useNavigation()/useFetcher() formMethod fields as uppercase HTTP methods to align with the fetch() (and some Remix) behavior. (#10207)

    • When future.v7_normalizeFormMethod is unspecified or set to false (default v6 behavior),
      • useNavigation().formMethod is lowercase
      • useFetcher().formMethod is lowercase
    • When future.v7_normalizeFormMethod === true:
      • useNavigation().formMethod is UPPERCASE
      • useFetcher().formMethod is UPPERCASE

Patch Changes

  • Fix createStaticHandler to also check for ErrorBoundary on routes in addition to errorElement (#10190)
  • Fix route ID generation when using Fragments in createRoutesFromElements (#10193)
  • Provide fetcher submission to shouldRevalidate if the fetcher action redirects (#10208)
  • Properly handle lazy() errors during router initialization (#10201)
  • Remove instanceof check for DeferredData to be resilient to ESM/CJS boundaries in SSR bundling scenarios (#10247)
  • Update to latest @remix-run/web-fetch@4.3.3 (#10216)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.9.0...react-router@6.10.0

v6.9.0

10 Mar 15:30
4ec107a
Compare
Choose a tag to compare

What's Changed

Minor Changes

  • React Router now supports an alternative way to define your route element and errorElement fields as React Components instead of React Elements. You can instead pass a React Component to the new Component and ErrorBoundary fields if you choose. There is no functional difference between the two, so use whichever approach you prefer πŸ˜€. You shouldn't be defining both, but if you do Component/ErrorBoundary will "win". (#10045)

    Example JSON Syntax

    // Both of these work the same:
    const elementRoutes = [{
      path: '/',
      element: <Home />,
      errorElement: <HomeError />,
    }]
    
    const componentRoutes = [{
      path: '/',
      Component: Home,
      ErrorBoundary: HomeError,
    }]
    
    function Home() { ... }
    function HomeError() { ... }

    Example JSX Syntax

    // Both of these work the same:
    const elementRoutes = createRoutesFromElements(
      <Route path='/' element={<Home />} errorElement={<HomeError /> } />
    );
    
    const componentRoutes = createRoutesFromElements(
      <Route path='/' Component={Home} ErrorBoundary={HomeError} />
    );
    
    function Home() { ... }
    function HomeError() { ... }
  • Introducing Lazy Route Modules! (#10045)

    In order to keep your application bundles small and support code-splitting of your routes, we've introduced a new lazy() route property. This is an async function that resolves the non-route-matching portions of your route definition (loader, action, element/Component, errorElement/ErrorBoundary, shouldRevalidate, handle).

    Lazy routes are resolved on initial load and during the loading or submitting phase of a navigation or fetcher call. You cannot lazily define route-matching properties (path, index, children) since we only execute your lazy route functions after we've matched known routes.

    Your lazy functions will typically return the result of a dynamic import.

    // In this example, we assume most folks land on the homepage so we include that
    // in our critical-path bundle, but then we lazily load modules for /a and /b so
    // they don't load until the user navigates to those routes
    let routes = createRoutesFromElements(
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="a" lazy={() => import("./a")} />
        <Route path="b" lazy={() => import("./b")} />
      </Route>
    );

    Then in your lazy route modules, export the properties you want defined for the route:

    export async function loader({ request }) {
      let data = await fetchData(request);
      return json(data);
    }
    
    // Export a `Component` directly instead of needing to create a React Element from it
    export function Component() {
      let data = useLoaderData();
    
      return (
        <>
          <h1>You made it!</h1>
          <p>{data}</p>
        </>
      );
    }
    
    // Export an `ErrorBoundary` directly instead of needing to create a React Element from it
    export function ErrorBoundary() {
      let error = useRouteError();
      return isRouteErrorResponse(error) ? (
        <h1>
          {error.status} {error.statusText}
        </h1>
      ) : (
        <h1>{error.message || error}</h1>
      );
    }

    An example of this in action can be found in the examples/lazy-loading-router-provider directory of the repository. For more info, check out the lazy docs.

    πŸ™Œ Huge thanks to @rossipedia for the Initial Proposal and POC Implementation.

Patch Changes

  • Improve memoization for context providers to avoid unnecessary re-renders (#9983)
  • Fix generatePath incorrectly applying parameters in some cases (#10078)
  • [react-router-dom-v5-compat] Add missed data router API re-exports (#10171)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.8.2...react-router@6.9.0

v6.8.2

27 Feb 20:39
c312eaa
Compare
Choose a tag to compare

What's Changed

  • Treat same-origin absolute URLs in <Link to> as external if they are outside of the router basename (#10135)
  • Correctly perform a hard redirect for same-origin absolute URLs outside of the router basename (#10076)
  • Fix SSR of absolute <Link to> urls (#10112)
  • Properly escape HTML characters in StaticRouterProvider serialized hydration data (#10068)
  • Fix useBlocker to return IDLE_BLOCKER during SSR (#10046)
  • Ensure status code and headers are maintained for defer loader responses in createStaticHandler's query() method (#10077)
  • Change invariant to an UNSAFE_invariant export since it's only intended for internal use (#10066)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.8.1...react-router@6.8.2

v6.8.1

06 Feb 18:27
6bbd48c
Compare
Choose a tag to compare

What's Changed

  • Remove inaccurate console warning for POP navigations and update active blocker logic (#10030)
  • Only check for differing origin on absolute URL redirects (#10033)
  • Improved absolute url detection in Link component (now also supports mailto: urls) (#9994)
  • Fix partial object (search or hash only) pathnames losing current path value (#10029)

Full Changelog: https://github.com/remix-run/react-router/compare/react-router@6.8.0...react-router@6.8.1