fix(deps): update react-router monorepo to v6.22.3 #3

Merged
kjuulh merged 1 commits from renovate/react-router-monorepo into main 2024-04-07 01:36:54 +02:00
Owner

This PR contains the following updates:

Package Type Update Change
react-router dependencies minor 6.0.0-beta.0 -> 6.22.3
react-router-dom dependencies minor 6.0.0-beta.0 -> 6.22.3

Release Notes

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

v6.22.3

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.15.3

v6.22.2

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.15.2

v6.22.1

Compare Source

Patch Changes
  • Fix encoding/decoding issues with pre-encoded dynamic parameter values (#​11199)
  • Updated dependencies:
    • @remix-run/router@1.15.1

v6.22.0

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.15.0

v6.21.3

Compare Source

Patch Changes
  • Remove leftover unstable_ prefix from Blocker/BlockerFunction types (#​11187)

v6.21.2

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.14.2

v6.21.1

Compare Source

Patch Changes
  • Fix bug with route.lazy not working correctly on initial SPA load when v7_partialHydration is specified (#​11121)
  • Updated dependencies:
    • @remix-run/router@1.14.1

v6.21.0

Compare Source

Minor Changes
  • Add a new future.v7_relativeSplatPath flag to implement a breaking bug fix to relative routing when inside a splat route. (#​11087)

    This fix was originally added in #​10983 and was later reverted in #​11078 because it was determined that a large number of existing applications were relying on the buggy behavior (see #​11052)

    The Bug
    The buggy behavior is that without this flag, the default behavior when resolving relative paths is to ignore any splat (*) portion of the current route path.

    The Background
    This decision was originally made thinking that it would make the concept of nested different sections of your apps in <Routes> easier if relative routing would replace the current splat:

    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="dashboard/*" element={<Dashboard />} />
      </Routes>
    </BrowserRouter>
    

    Any paths like /dashboard, /dashboard/team, /dashboard/projects will match the Dashboard route. The dashboard component itself can then render nested <Routes>:

    function Dashboard() {
      return (
        <div>
          <h2>Dashboard</h2>
          <nav>
            <Link to="/">Dashboard Home</Link>
            <Link to="team">Team</Link>
            <Link to="projects">Projects</Link>
          </nav>
    
          <Routes>
            <Route path="/" element={<DashboardHome />} />
            <Route path="team" element={<DashboardTeam />} />
            <Route path="projects" element={<DashboardProjects />} />
          </Routes>
        </div>
      );
    }
    

    Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the Dashboard as its own independent app, or embed it into your large app without making any changes to it.

    The Problem

    The problem is that this concept of ignoring part of a path breaks a lot of other assumptions in React Router - namely that "." always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using ".":

    // If we are on URL /dashboard/team, and we want to link to /dashboard/team:
    function DashboardTeam() {
      // ❌ This is broken and results in <a href="/dashboard">
      return <Link to=".">A broken link to the Current URL</Link>;
    
      // ✅ This is fixed but super unintuitive since we're already at /dashboard/team!
      return <Link to="./team">A broken link to the Current URL</Link>;
    }
    

    We've also introduced an issue that we can no longer move our DashboardTeam component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as /dashboard/:widget. Now, our "." links will, properly point to ourself inclusive of the dynamic param value so behavior will break from it's corresponding usage in a /dashboard/* route.

    Even worse, consider a nested splat route configuration:

    <BrowserRouter>
      <Routes>
        <Route path="dashboard">
          <Route path="*" element={<Dashboard />} />
        </Route>
      </Routes>
    </BrowserRouter>
    

    Now, a <Link to="."> and a <Link to=".."> inside the Dashboard component go to the same place! That is definitely not correct!

    Another common issue arose in Data Routers (and Remix) where any <Form> should post to it's own route action if you the user doesn't specify a form action:

    let router = createBrowserRouter({
      path: "/dashboard",
      children: [
        {
          path: "*",
          action: dashboardAction,
          Component() {
            // ❌ This form is broken!  It throws a 405 error when it submits because
            // it tries to submit to /dashboard (without the splat value) and the parent
            // `/dashboard` route doesn't have an action
            return <Form method="post">...</Form>;
          },
        },
      ],
    });
    

    This is just a compounded issue from the above because the default location for a Form to submit to is itself (".") - and if we ignore the splat portion, that now resolves to the parent route.

    The Solution
    If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage ../ for any links to "sibling" pages:

    <BrowserRouter>
      <Routes>
        <Route path="dashboard">
          <Route index path="*" element={<Dashboard />} />
        </Route>
      </Routes>
    </BrowserRouter>
    
    function Dashboard() {
      return (
        <div>
          <h2>Dashboard</h2>
          <nav>
            <Link to="..">Dashboard Home</Link>
            <Link to="../team">Team</Link>
            <Link to="../projects">Projects</Link>
          </nav>
    
          <Routes>
            <Route path="/" element={<DashboardHome />} />
            <Route path="team" element={<DashboardTeam />} />
            <Route path="projects" element={<DashboardProjects />} />
          </Router>
        </div>
      );
    }
    

    This way, . means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and .. always means "my parents pathname".

Patch Changes
  • Properly handle falsy error values in ErrorBoundary's (#​11071)
  • Updated dependencies:
    • @remix-run/router@1.14.0

v6.20.1

Compare Source

Patch Changes
  • Revert the useResolvedPath fix for splat routes due to a large number of applications that were relying on the buggy behavior (see #​11052 (comment)). We plan to re-introduce this fix behind a future flag in the next minor version. (#​11078)
  • Updated dependencies:
    • @remix-run/router@1.13.1

v6.20.0

Compare Source

Minor Changes
  • Export the PathParam type from the public API (#​10719)
Patch Changes
  • Fix bug with resolveTo in splat routes (#​11045)
    • This is a follow up to #​10983 to handle the few other code paths using getPathContributingMatches
    • This removes the UNSAFE_getPathContributingMatches export from @remix-run/router since we no longer need this in the react-router/react-router-dom layers
  • Updated dependencies:
    • @remix-run/router@1.13.0

v6.19.0

Compare Source

Minor Changes
  • Add unstable_flushSync option to useNavigate/useSumbit/fetcher.load/fetcher.submit to opt-out of React.startTransition and into ReactDOM.flushSync for state updates (#​11005)
  • Remove the unstable_ prefix from the useBlocker hook as it's been in use for enough time that we are confident in the API. We do not plan to remove the prefix from unstable_usePrompt due to differences in how browsers handle window.confirm that prevent React Router from guaranteeing consistent/correct behavior. (#​10991)
Patch Changes
  • Fix useActionData so it returns proper contextual action data and not any action data in the tree (#​11023)

  • Fix bug in useResolvedPath that would cause useResolvedPath(".") in a splat route to lose the splat portion of the URL path. (#​10983)

    • ⚠️ This fixes a quite long-standing bug specifically for "." paths inside a splat route which incorrectly dropped the splat portion of the URL. If you are relative routing via "." inside a splat route in your application you should double check that your logic is not relying on this buggy behavior and update accordingly.
  • Updated dependencies:

    • @remix-run/router@1.12.0

v6.18.0

Compare Source

Patch Changes
  • Fix the future prop on BrowserRouter, HashRouter and MemoryRouter so that it accepts a Partial<FutureConfig> instead of requiring all flags to be included. (#​10962)
  • Updated dependencies:
    • @remix-run/router@1.11.0

v6.17.0

Compare Source

Patch Changes
  • Fix RouterProvider future prop type to be a Partial<FutureConfig> so that not all flags must be specified (#​10900)
  • Updated dependencies:
    • @remix-run/router@1.10.0

v6.16.0

Compare Source

Minor Changes
  • In order to move towards stricter TypeScript support in the future, we're aiming to replace current usages of any with unknown on exposed typings for user-provided data. To do this in Remix v2 without introducing breaking changes in React Router v6, we have added generics to a number of shared types. These continue to default to any in React Router and are overridden with unknown in Remix. In React Router v7 we plan to move these to unknown as a breaking change. (#​10843)
    • Location now accepts a generic for the location.state value
    • ActionFunctionArgs/ActionFunction/LoaderFunctionArgs/LoaderFunction now accept a generic for the context parameter (only used in SSR usages via createStaticHandler)
    • The return type of useMatches (now exported as UIMatch) accepts generics for match.data and match.handle - both of which were already set to unknown
  • Move the @private class export ErrorResponse to an UNSAFE_ErrorResponseImpl export since it is an implementation detail and there should be no construction of ErrorResponse instances in userland. This frees us up to export a type ErrorResponse which correlates to an instance of the class via InstanceType. Userland code should only ever be using ErrorResponse as a type and should be type-narrowing via isRouteErrorResponse. (#​10811)
  • Export ShouldRevalidateFunctionArgs interface (#​10797)
  • Removed private/internal APIs only required for the Remix v1 backwards compatibility layer and no longer needed in Remix v2 (_isFetchActionRedirect, _hasFetcherDoneAnything) (#​10715)
Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.9.0

v6.15.0

Compare Source

Minor Changes
  • Add's a new redirectDocument() function which allows users to specify that a redirect from a loader/action should trigger a document reload (via window.location) instead of attempting to navigate to the redirected location via React Router (#​10705)
Patch Changes
  • Ensure useRevalidator is referentially stable across re-renders if revalidations are not actively occurring (#​10707)
  • Updated dependencies:
    • @remix-run/router@1.8.0

v6.14.2

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.7.2

v6.14.1

Compare Source

Patch Changes
  • Fix loop in unstable_useBlocker when used with an unstable blocker function (#​10652)
  • Fix issues with reused blockers on subsequent navigations (#​10656)
  • Updated dependencies:
    • @remix-run/router@1.7.1

v6.14.0

Compare Source

Patch Changes
  • Strip basename from locations provided to unstable_useBlocker functions to match useLocation (#​10573)
  • Fix generatePath when passed a numeric 0 value parameter (#​10612)
  • Fix unstable_useBlocker key issues in StrictMode (#​10573)
  • Fix tsc --skipLibCheck:false issues on React 17 (#​10622)
  • Upgrade typescript to 5.1 (#​10581)
  • Updated dependencies:
    • @remix-run/router@1.7.0

v6.13.0

Compare Source

Minor Changes
  • Move React.startTransition usage behind a future flag to avoid issues with existing incompatible Suspense usages. We recommend folks adopting this flag to be better compatible with React concurrent mode, but if you run into issues you can continue without the use of startTransition until v7. Issues usually boils down to creating net-new promises during the render cycle, so if you run into issues you should either lift your promise creation out of the render cycle or put it behind a useMemo. (#​10596)

    Existing behavior will no longer include React.startTransition:

    <BrowserRouter>
      <Routes>{/*...*/}</Routes>
    </BrowserRouter>
    
    <RouterProvider router={router} />
    

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

    <BrowserRouter future={{ v7_startTransition: true }}>
      <Routes>{/*...*/}</Routes>
    </BrowserRouter>
    
    <RouterProvider router={router} future={{ v7_startTransition: true }}/>
    
Patch Changes
  • Work around webpack/terser React.startTransition minification bug in production mode (#​10588)

v6.12.1

Compare Source

!WARNING]
Please use version `6.13.0` or later instead of `6.12.1`. This version suffers from a `webpack`/`terser` minification issue resulting in invalid minified code in your resulting production bundles which can cause issues in your application. See [#&#8203;10579](https://github.com/remix-run/react-router/issues/10579) for more details.
Patch Changes
  • Adjust feature detection of React.startTransition to fix webpack + react 17 compilation error (#​10569)

v6.12.0

Compare Source

Minor Changes
  • Wrap internal router state updates with React.startTransition if it exists (#​10438)
Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.6.3

v6.11.2

Compare Source

Patch Changes
  • Fix basename duplication in descendant <Routes> inside a <RouterProvider> (#​10492)
  • Updated dependencies:
    • @remix-run/router@1.6.2

v6.11.1

Compare Source

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)
  • Updated dependencies:
    • @remix-run/router@1.6.1

v6.11.0

Compare Source

Patch Changes
  • Log loader/action errors to the console in dev for easier stack trace evaluation (#​10286)
  • Fix bug preventing rendering of descendant <Routes> when RouterProvider errors existed (#​10374)
  • Fix inadvertent re-renders when using Component instead of element on a route definition (#​10287)
  • 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)
  • 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 footguns in useEffect calls. (#​10377, #​10409)
  • Allow useRevalidator() to resolve a loader-driven error boundary scenario (#​10369)
  • Avoid unnecessary unsubscribe/resubscribes on router state changes (#​10409)
  • 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(). When using BrowserRouter, these hooks remain unstable across location changes because they still rely on useLocation(). (#​10336)
  • Updated dependencies:
    • @remix-run/router@1.6.0

v6.10.0

Compare Source

Minor Changes
  • Added support for Future Flags in React Router. The first 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() behavior. (#​10207)

    • When future.v7_normalizeFormMethod === 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 route ID generation when using Fragments in createRoutesFromElements (#​10193)
  • Updated dependencies:
    • @remix-run/router@1.5.0

v6.9.0

Compare Source

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.

    🙌 Huge thanks to @​rossipedia for the Initial Proposal and POC Implementation.

  • Updated dependencies:

    • @remix-run/router@1.4.0
Patch Changes
  • Fix generatePath incorrectly applying parameters in some cases (#​10078)
  • Improve memoization for context providers to avoid unnecessary re-renders (#​9983)

v6.8.2

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.3.3

v6.8.1

Compare Source

Patch Changes
  • Remove inaccurate console warning for POP navigations and update active blocker logic (#​10030)
  • Updated dependencies:
    • @remix-run/router@1.3.2

v6.8.0

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.3.1

v6.7.0

Compare Source

Minor Changes
  • Add unstable_useBlocker hook for blocking navigations within the app's location origin (#​9709)
Patch Changes
  • Fix generatePath when optional params are present (#​9764)
  • Update <Await> to accept ReactNode as children function return result (#​9896)
  • Updated dependencies:
    • @remix-run/router@1.3.0

v6.6.2

Compare Source

Patch Changes
  • Ensure useId consistency during SSR (#​9805)

v6.6.1

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.2.1

v6.6.0

Compare Source

Patch Changes
  • Prevent useLoaderData usage in errorElement (#​9735)
  • Updated dependencies:
    • @remix-run/router@1.2.0

v6.5.0

Compare Source

This release introduces support for Optional Route Segments. Now, adding a ? to the end of any path segment will make that entire segment optional. This works for both static segments and dynamic parameters.

Optional Params Examples

  • <Route path=":lang?/about> will match:
    • /:lang/about
    • /about
  • <Route path="/multistep/:widget1?/widget2?/widget3?"> will match:
    • /multistep
    • /multistep/:widget1
    • /multistep/:widget1/:widget2
    • /multistep/:widget1/:widget2/:widget3

Optional Static Segment Example

  • <Route path="/home?"> will match:
    • /
    • /home
  • <Route path="/fr?/about"> will match:
    • /about
    • /fr/about
Minor Changes
  • Allows optional routes and optional static segments (#​9650)
Patch Changes
  • Stop incorrectly matching on partial named parameters, i.e. <Route path="prefix-:param">, to align with how splat parameters work. If you were previously relying on this behavior then it's recommended to extract the static portion of the path at the useParams call site: (#​9506)
// Old behavior at URL /prefix-123
<Route path="prefix-:id" element={<Comp /> }>

function Comp() {
  let params = useParams(); // { id: '123' }
  let id = params.id; // "123"
  ...
}

// New behavior at URL /prefix-123
<Route path=":id" element={<Comp /> }>

function Comp() {
  let params = useParams(); // { id: 'prefix-123' }
  let id = params.id.replace(/^prefix-/, ''); // "123"
  ...
}
  • Updated dependencies:
    • @remix-run/router@1.1.0

v6.4.5

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.0.5

v6.4.4

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.0.4

v6.4.3

Compare Source

Patch Changes
  • useRoutes should be able to return null when passing locationArg (#​9485)
  • fix initialEntries type in createMemoryRouter (#​9498)
  • Updated dependencies:
    • @remix-run/router@1.0.3

v6.4.2

Compare Source

Patch Changes
  • Fix IndexRouteObject and NonIndexRouteObject types to make hasErrorElement optional (#​9394)
  • Enhance console error messages for invalid usage of data router hooks (#​9311)
  • If an index route has children, it will result in a runtime error. We have strengthened our RouteObject/RouteProps types to surface the error in TypeScript. (#​9366)
  • Updated dependencies:
    • @remix-run/router@1.0.2

v6.4.1

Compare Source

Patch Changes
  • Preserve state from initialEntries (#​9288)
  • Updated dependencies:
    • @remix-run/router@1.0.1

v6.4.0

Compare Source

Whoa this is a big one! 6.4.0 brings all the data loading and mutation APIs over from Remix. Here's a quick high level overview, but it's recommended you go check out the docs, especially the feature overview and the tutorial.

New APIs

  • Create your router with createMemoryRouter
  • Render your router with <RouterProvider>
  • Load data with a Route loader and mutate with a Route action
  • Handle errors with Route errorElement
  • Defer non-critical data with defer and Await

Bug Fixes

  • Path resolution is now trailing slash agnostic (#​8861)
  • useLocation returns the scoped location inside a <Routes location> component (#​9094)

Updated Dependencies

  • @remix-run/router@1.0.0

v6.3.0: react-router@v6.3.0

Compare Source

What's Changed
New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.2.2...v6.3.0

v6.2.2

Compare Source

What's Changed
🐛 Bug Fixes
  • Fixed nested splat routes that begin with special URL-safe characters (#​8563)
  • Fixed a bug where index routes were missing route context in some cases (#​8497)
New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.2.1...v6.2.2

v6.2.1

Compare Source

This release updates the internal history dependency to 5.2.0.

Full Changelog: https://github.com/remix-run/react-router/compare/v6.2.0...v6.2.1

v6.2.0

Compare Source

🐛 Bug fixes

  • Fixed the RouteProps element type, which should be a ReactNode (#​8473)
  • Fixed a bug with useOutlet for top-level routes (#​8483)

Features

  • We now use statically analyzable CJS exports. This enables named imports in Node ESM scripts (See the commit).

New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.1.1...v6.2.0

v6.1.1

Compare Source

In v6.1.0 we inadvertently shipped a new, undocumented API that will likely introduce bugs (#​7586). We have flagged HistoryRouter as unstable_HistoryRouter, as this API will likely need to change before a new major release.

Full Changelog: https://github.com/remix-run/react-router/compare/v6.1.0...v6.1.1

v6.1.0

Compare Source

🐛 Bug fixes

  • Fixed a bug that broke support for base64 encoded IDs on nested routes (#​8291)

Features

  • <Outlet> can now receive a context prop. This value is passed to child routes and is accessible via the new useOutletContext hook. See the API docs for details. (#​8461)
  • <NavLink> can now receive a child function for access to its props. (#​8164)

💅 Enhancements

  • Improved TypeScript signature for useMatch and matchPath. For example, when you call useMatch("foo/:bar/:baz"), the path is parsed and the return type will be PathMatch<"bar" | "baz">. (#​8030)
  • A few error message improvements (#​8202)

New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.0.1...v6.1.0

v6.0.2

Compare Source

Features

  • Added the reloadDocument prop to <Link>. This allows <Link> to function like a normal anchor tag by reloading the document after navigation while maintaining the relative to resolution.

🗒️ Docs

  • Fixed several issues in docblocks and the docs themselves. See the full changelog for the deets!

🤝 New Contributors

Full Changelog

v6.0.1

Compare Source

🐛 Bug Fixes

  • Add a default <StaticRouter location> value (#​8243)
  • Add invariant for using <Route> inside <Routes> to help people make the change (#​8238)

v6.0.0

Compare Source

React Router v6 is here!

Please go read our blog post for more information on all the great stuff in v6 including notes about how to upgrade from React Router v5 and Reach Router.

v6.0.0-beta.8

Compare Source

Remember last week when we said

We anticipate this will be the last beta release before v6 stable next week.

Yeah, about that … 😅

We found and squashed a few high-priority bugs that needed to be addressed first. But it's coming very soon, we promise! In the mean time, here's what you'll get from our eight-est and greatest beta release:

🐛 Bug Fixes

  • We fixed a few bugs in useHref that resulted in the incorrect resolved value in cases where a basename is used on the <Router /> component (See #​8133 and #​8142 for details).
  • We also fixed a bug in our path ranking algorithm so that splat routes (routes with a * path value) are now correctly ranked ahead of layout routes.

🗒️ Docs

We've added lots of goodies to our docs and examples, and there's a lot more yet to come. Take a look and see if you find something that makes your work a little easier! We think the lazy loading and custom query parsing examples are particularly cool! 🤓

v6.0.0-beta.7

Compare Source

In this release we made a small but significant change to how <Link to=".."> works. This is going to help out a lot if you were trying to use links in a * route.

We have also backed out our blocking/prompt APIs for the stable v6 release. We will revisit this post 6.0 when we have a little more time to get it right.

Features

The major change in this release could also be classified as a bugfix or a breaking change, depending on how you look at it. We essentialy altered the way <Link to=".."> works. See #​8086 for the motivation behind this change.

You'll probably want to reread the section in the v5 => v6 migration guide about <Link to> values (it has been updated), but it basically boils down to this: any leading .. segment in a <Link to> value traverses "up" one route and builds upon that route's path instead of just removing one URL segment. This feature really completes the story of relative routes and links.

We could consider this a bugfix, since this is how it was always intended to work in the first place. Without it, you'd have a difficult time linking predictably in * routes because your <a href> would be different depending on the number of segments in the current URL.

The reason this could also be considered a breaking change is that .. now works slightly differently in <Link to> than it would in <a href>. When you have <a href=".."> it operates on the URL pathname, removing one segment of the current URL. However, since many routes really only match a single segment of the URL, there is often no difference between <Link to=".."> and <a href="..">.

💔 Breaking Changes

  • We removed useBlocker(), usePrompt(), and <Prompt> for now. We will revisit these post 6.0 when we have more time to get it right. But we don't want it to block (see what I did there) the release of all the other awesome stuff we've got in v6.

🛠 Roadmap

We anticipate this will be the last beta release before v6 stable next week. Please give it a shot and let us know how it goes!

👍 Upgrading

If you're thinking about upgrading to v6, I published a few notes this past week that may help you:

Both of those posts contain steps you can take today in your v5 app without upgrading to v6.

We are also developing a backwards compat lib that should help some of you upgrade from v5 to v6. We'll post more about this when it's ready.

💻 Installing

Development for v6 has switched from dev to the main branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.6

Compare Source

No big enhancements in this release, just squashing bugs and writing lots of tests! Also, we are hard at work on cranking out examples for v6. See the end of this post for an update on our roadmap between here and v6 stable.

🧰 Examples

We have begun creating some examples for v6 that we hope will help developers make effective use of all the new features we have. So far, we have examples for the following:

  • Basic Example – A basic client-side app for v6 showing how to use nested routes, layouts, links, and the new <Outlet> API
  • Auth Example – Demonstrates an authentication flow including using the new useNavigate() hook, the <Navigate> element, and location.state
  • Search Params Example – Demonstrates how to build a simple search form that uses the new useSearchParams() hook
  • SSR Example – A server-rendered app that uses <StaticRouter> on the server and uses a <BrowserRouter> with ReactDOM.hydrate() on the client

Each example includes a button in the README that allows you to instantly launch a running instance on StackBlitz that you can play with. We hope you enjoy exploring!

🐛 Bugfixes

  • Make <NavLink> match only whole URL segments instead of pieces. This means that <NavLink to="/home/users"> will still be active at /home/users, but not at /home/users2. See #​7523
  • Makes "layout routes" (routes with no path) never match unless one of their children do. See #​8085
  • Fixes a route matching regression with splat routes that was introduced in beta.5. See #​8072 and #​8109
  • Fixes matching a nested splat route. See af7d038
  • Provide all parent route params to descendant <Routes>. This reverses a decision that we made in beta.5 to remove them. See #​8073

💔 Breaking Changes

  • Splats in route paths (*) match only after a / in the URL. This means that <Route path="files*"> will always match as if it were <Route path="files/*">. The router will issue a warning if your route path ends with * but not /*

🛠 Roadmap

We are very close to a stable release! The last big code changes we need to make are:

  • Fixing "linking up". Currently a <Link to=".."> operates on the URL pathname. However, this makes it difficult to link to the parent route when you're in a splat route. See #​8086. This will be a breaking change.
  • We are going to remove useBlocker() and <Prompt> in our initial v6 release, with plans to revisit them and possibly add them back at some point in the future. I still need to write up something here that explains our rationale. This will also be a breaking change.
  • We are going to add some animation primitives (see https://github.com/remix-run/react-router/discussions/8008). The <Routes location> prop will be in v6, but it isn't ideal for animation.

💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.5

Compare Source

This week's release adds some much-needed polish to a few niche features of the router: splat routes (a route that uses a * path) and basenames. It also adds a renderMatches API that completes the story for those of you who may have been using react-router-config in v4 and v5.

🐛 Bugfixes

  • A * in a child route path matches after a slash following its parent route path. This fixes some situations where the * was overly greedy (see #​7972)
  • Resolution of <Link to="."> and useResolvedPath(".") values are fixed in splat routes. Previously these resolved relative to the parent route's path. They now resolve relative to the path of the route that rendered them.

Enhancements

This release makes it easier to work with apps that have multiple entry points. Using the <Router basename> prop allows React Router to be easily deployed on only a portion of a larger site by using a portion of the URL pathname (the "basename") to transparently prefix all route paths and link navigations.

For example, you can deploy one React Router app at the /inbox URL prefix, and another one at the /admin prefix. These base URLs represent two different entry points into your app, each with its own bundles. The rest of your site, including the root / URL could be rendered by something other than React Router, for example by your server framework of choice.

In the bundle for each entry point, simply initialize React Router with the basename of that entry point.

<Router basename="/inbox">
  // ...
</Router>

Then define your routes and link paths without using the /inbox URL prefix in any of them. The entire app will run relative to that prefix.

Another improvement in this release is the addition of the renderMatches API, which is the complement of matchRoutes. These APIs are both very low-level and should not normally be needed. But they are sometimes nice to use if you are doing your own data loading using the array of matches that you get back from matchRoutes.

matchRoutes and renderMatches are the equivalent of the react-router-config package we shipped in v4 and v5, just built directly into the router instead of in a separate package.

💔 Breaking Changes

  • <Routes basename> has moved to <Router basename>. This prop is also available on all router variants (<BrowserRouter>, <HashRouter>, etc.).
  • useLocation().pathname no longer includes the basename, if present.
  • The basename argument was removed from useRoutes. This reverts the signature to useRoutes(routes, location), same as it was previous to beta.4.
  • Descendant <Routes> do not get the params from their parents. This helps a set of <Routes> to be more portable by decoupling it from the params of its parents and makes it easier to know which params will be returned from useParams(). If you were relying on this behavior previously, you'll need to pass along the params manually to the elements rendered by the descendant <Routes>. See this comment for an example of how this is to be done and for a potential workaround if you really need the old behavior.
  • match.pathname in a splat route now includes the portion of the pathname matched by the *. This makes the * param behave much more like other dynamic :id-style params.
  • Resolution of relative <Link>s in splat routes is changed now because the entire pathname that was matched by that route is now different (see previous bullet). Instead of resolving relative to the portion of the pathname before the *, paths resolve relative to the full pathname that was matched by the route.

💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.4

Compare Source

Last week we released a lot of nice little bug features, but we did get a little carried away and let a little bug slip through with relative path resolution. Our bad! That nasty lil' guy is squashed in this week's beta. 🐛

And there's more! Let's dive in…

🐛 Bugfixes

  • Path resolution for nested relative routes was broken in the last release and should now be fixed. Nested routes construct their pathname based on the location of their parent, not the current location. This is explained in detail under Relative Routes and Links in our advanced guides, and the issue itself in #​8004

Enhancements

  • We made some enhancements with the Params type which is now generic, so you can add your own types if you know what to expect from functions that return query parameters. (#​8019)
// before
let { valid, invalid } = useParams(); // No problems here!

let match = useMatch("profile/:userId");
let userId = match?.params.user; // wrong param, but TS doesn't know that!

// after:
let { valid, invalid } = useParams<"valid" | "key">(); // Property 'invalid' does not exist on type 'Params<"valid" | "key">'

let match = useMatch<"userId">("profile/:userId");
let userId = match?.params.user; // Property 'user' does not exist on type 'Params<"userId">'
  • Absolute nested path support

There was quite a bit of discussion in #​7335 from people who are using constants to define their route paths. In this style, paths are often written as absolute paths from the root / URL. These constants are then able to be used both in <Route path> definitions as well as <Link to> values. It usually looks something like this:

const USERS_PATH = "/users";
const USERS_INDEX_PATH = `${USERS_PATH}/`;
const USER_PROFILE_PATH = `${USERS_PATH}/:id`;

function UsersRoutes() {
  return (
    <Routes>
      <Route path={USERS_PATH} element={<UsersLayout />}>
        <Route path={USERS_INDEX_PATH} element={<UsersIndex />} />
        <Route path={USER_PROFILE_PATH} element={<UserProfile />} />
      </Route>
    </Routes>
  );
}

This style of use is now fully supported in v6. This is great for people who write their apps like this, but it technically could cause some breakage if you were using absolute paths (that start with /) in nested routes in previous betas. To fix this, simply remove the / from the beginning of any route paths that are meant to be relative. React Router will throw an error if you are using absolute paths that don't match their parent route paths. Hopefully this should help you find them if you are upgrading.

If you were using <Route path="/"> to indicate an index route, you can now use the new <Route index> prop to accomplish the same thing. The index prop makes it easy to scan a route config to find the index route. It also provides a guarantee that nobody will ever add children to that route.

Here's the same route config as the one above, but rewritten with relative paths and the index prop:

function UsersRoutes() {
  return (
    <Routes>
      <Route path="users" element={<UsersLayout />}>
        <Route index element={<UsersIndex />} />
        <Route path=":id" element={<UserProfile />} />
      </Route>
    </Routes>
  );
}

A lot of our work on React Router is about doing the least surprising thing for our users. Allowing absolute paths in nested routes gets us a little closer to that goal!

💔 Breaking Changes

  • Removed the ability for nested route paths to begin with a / and not contain the complete path of their parent routes. This was necessary in order to introduce support for absolute paths in nested routes, described in detail above

  • Removed the createRoutesFromArray utility function. You can now pass your routes directly to useRoutes or matchRoutes without passing it through createRoutesFromArray first

  • Removed the PartialRouteObject type. If you were importing and using this type before, use RouteObject instead, which has been updated to make all properties optional

  • The useRoutes API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object:

// Before
useRoutes([...routes], basename);

// After
useRoutes([...routes], { basename });
  • The matchPath function now returns match.pattern instead of match.path, which is a little more descriptive about what it actually is

💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.3

Compare Source

Loads of goodies for you this week, as well as a few breaking changes for all of you eager beavers who are brave enough to use beta software in production! 🦫

(seriously, thank you all for helping us tighten up our APIs and fix nasty bugs)

💔 Breaking Changes!

  • NavLink no longer supports the activeClassName or activeStyle props. Instead, we provide a more powerful API that allows you to pass functions to either the className or style props to conditionally apply values based on the link's active state. While a bit more verbose in some cases, this offers a nicer experience for folks who use utility class-based CSS. (#​7194)
// Before
<NavLink className="link" activeClassName="active-link" />
<NavLink style={{ color: "blue" }} activeStyle={{ color: "green" }} />

// After
<NavLink
  className={({ isActive }) =>
    `link ${
      isActive
        ? "active-link"
        : // Couldn't do this before!
          "inactive-link"
    }`
  }
/>
<NavLink style={({ isActive }) => ({ color: isActive ? "green" : "blue" })} />

Note: You can always abstract over this feature in a custom NavLink if you prefer the old v5 API.

  • The useRoutes API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object:
// Before
useRoutes([...routes], basename);

// After
useRoutes([...routes], { basename });

🐛 Bugfixes

  • The basename prop on Routes is treated as case-insensitive (#​7997)
  • useNavigate previously used the incorrect pathname when called from parent routes when the URL matches one of its children. This fix also applies to useSearchParams (#​7880)

Enhancements

  • Routes and useRoutes now allow you to override the location, which may be useful when building some modal interfaces and route transition animations. We are working hard to update our docs to include examples for advanced patterns where this might be useful, but in the mean time this also brings Routes closer to feature parity with v5's Switch via the location prop. (#​7117)
  • Provided new hooks useClickHandler and usePressHandler to make customizing Links a bit easier. (#​7998)
    • Please note: with great power comes great responsibility. If you create a custom Link, be sure to render an actual HTML anchor element, otherwise your app will likely be inaccessible without a significant amount of additional work which, I assure you, you don't want to do!

💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

🙏 Credits

Thanks to @​andrelandgraf, @​dhulme, @​fgatti675, @​hugmanrique, @​MeiKatz, @​chaance and @​mjackson for your contributions!

v6.0.0-beta.2

Compare Source

🐛 Bugfixes

Enhancements

💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

🙏 Credits

Thanks to @​liho98, @​wojtekmaj, @​cravend, @​chaance and @​mjackson for your contributions!

Enjoy!

v6.0.0-beta.1

Compare Source

We're on the road to a stable v6 release!

There are no new features in this release since beta.0, but a handful of squashed bugs, perf enhancements, and DX improvements for TypeScript users.

🐛 Bugfixes

Enhancements

  • Internally we are separating navigator into a separate context object, meaning your components that call useNavigate will probably render a little less often. Wowza, much perf!
  • react-router-dom and react-router-native now re-exports all types exported from react-router

💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

🙏 Credits

Thanks to @​brookslybrand, @​bogdansoare, @​chaance and @​mjackson for your contributions!

Enjoy!

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

v6.22.3

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.15.3
    • react-router@6.22.3

v6.22.2

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.15.2
    • react-router@6.22.2

v6.22.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@6.22.1
    • @remix-run/router@1.15.1

v6.22.0

Compare Source

Minor Changes
  • Include a window__reactRouterVersion tag for CWV Report detection (#​11222)
Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.15.0
    • react-router@6.22.0

v6.21.3

Compare Source

Patch Changes
  • Fix NavLink isPending when a basename is used (#​11195)
  • Remove leftover unstable_ prefix from Blocker/BlockerFunction types (#​11187)
  • Updated dependencies:
    • react-router@6.21.3

v6.21.2

Compare Source

Patch Changes
  • Leverage useId for internal fetcher keys when available (#​11166)
  • Updated dependencies:
    • @remix-run/router@1.14.2
    • react-router@6.21.2

v6.21.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@6.21.1
    • @remix-run/router@1.14.1

v6.21.0

Compare Source

Minor Changes
  • Add a new future.v7_relativeSplatPath flag to implement a breaking bug fix to relative routing when inside a splat route. (#​11087)

    This fix was originally added in #​10983 and was later reverted in #​11078 because it was determined that a large number of existing applications were relying on the buggy behavior (see #​11052)

    The Bug
    The buggy behavior is that without this flag, the default behavior when resolving relative paths is to ignore any splat (*) portion of the current route path.

    The Background
    This decision was originally made thinking that it would make the concept of nested different sections of your apps in <Routes> easier if relative routing would replace the current splat:

    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="dashboard/*" element={<Dashboard />} />
      </Routes>
    </BrowserRouter>
    

    Any paths like /dashboard, /dashboard/team, /dashboard/projects will match the Dashboard route. The dashboard component itself can then render nested <Routes>:

    function Dashboard() {
      return (
        <div>
          <h2>Dashboard</h2>
          <nav>
            <Link to="/">Dashboard Home</Link>
            <Link to="team">Team</Link>
            <Link to="projects">Projects</Link>
          </nav>
    
          <Routes>
            <Route path="/" element={<DashboardHome />} />
            <Route path="team" element={<DashboardTeam />} />
            <Route path="projects" element={<DashboardProjects />} />
          </Routes>
        </div>
      );
    }
    

    Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the Dashboard as its own independent app, or embed it into your large app without making any changes to it.

    The Problem

    The problem is that this concept of ignoring part of a path breaks a lot of other assumptions in React Router - namely that "." always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using ".":

    // If we are on URL /dashboard/team, and we want to link to /dashboard/team:
    function DashboardTeam() {
      // ❌ This is broken and results in <a href="/dashboard">
      return <Link to=".">A broken link to the Current URL</Link>;
    
      // ✅ This is fixed but super unintuitive since we're already at /dashboard/team!
      return <Link to="./team">A broken link to the Current URL</Link>;
    }
    

    We've also introduced an issue that we can no longer move our DashboardTeam component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as /dashboard/:widget. Now, our "." links will, properly point to ourself inclusive of the dynamic param value so behavior will break from it's corresponding usage in a /dashboard/* route.

    Even worse, consider a nested splat route configuration:

    <BrowserRouter>
      <Routes>
        <Route path="dashboard">
          <Route path="*" element={<Dashboard />} />
        </Route>
      </Routes>
    </BrowserRouter>
    

    Now, a <Link to="."> and a <Link to=".."> inside the Dashboard component go to the same place! That is definitely not correct!

    Another common issue arose in Data Routers (and Remix) where any <Form> should post to it's own route action if you the user doesn't specify a form action:

    let router = createBrowserRouter({
      path: "/dashboard",
      children: [
        {
          path: "*",
          action: dashboardAction,
          Component() {
            // ❌ This form is broken!  It throws a 405 error when it submits because
            // it tries to submit to /dashboard (without the splat value) and the parent
            // `/dashboard` route doesn't have an action
            return <Form method="post">...</Form>;
          },
        },
      ],
    });
    

    This is just a compounded issue from the above because the default location for a Form to submit to is itself (".") - and if we ignore the splat portion, that now resolves to the parent route.

    The Solution
    If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage ../ for any links to "sibling" pages:

    <BrowserRouter>
      <Routes>
        <Route path="dashboard">
          <Route index path="*" element={<Dashboard />} />
        </Route>
      </Routes>
    </BrowserRouter>
    
    function Dashboard() {
      return (
        <div>
          <h2>Dashboard</h2>
          <nav>
            <Link to="..">Dashboard Home</Link>
            <Link to="../team">Team</Link>
            <Link to="../projects">Projects</Link>
          </nav>
    
          <Routes>
            <Route path="/" element={<DashboardHome />} />
            <Route path="team" element={<DashboardTeam />} />
            <Route path="projects" element={<DashboardProjects />} />
          </Router>
        </div>
      );
    }
    

    This way, . means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and .. always means "my parents pathname".

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.14.0
    • react-router@6.21.0

v6.20.1

Compare Source

Patch Changes
  • Revert the useResolvedPath fix for splat routes due to a large number of applications that were relying on the buggy behavior (see #​11052 (comment)). We plan to re-introduce this fix behind a future flag in the next minor version. (#​11078)
  • Updated dependencies:
    • react-router@6.20.1
    • @remix-run/router@1.13.1

v6.20.0

Compare Source

Minor Changes
  • Export the PathParam type from the public API (#​10719)
Patch Changes
  • Updated dependencies:
    • react-router@6.20.0
    • @remix-run/router@1.13.0

v6.19.0

Compare Source

Minor Changes
  • Add unstable_flushSync option to useNavigate/useSumbit/fetcher.load/fetcher.submit to opt-out of React.startTransition and into ReactDOM.flushSync for state updates (#​11005)
  • Allow unstable_usePrompt to accept a BlockerFunction in addition to a boolean (#​10991)
Patch Changes
  • Fix issue where a changing fetcher key in a useFetcher that remains mounted wasn't getting picked up (#​11009)
  • Fix useFormAction which was incorrectly inheriting the ?index query param from child route action submissions (#​11025)
  • Fix NavLink active logic when to location has a trailing slash (#​10734)
  • Updated dependencies:
    • react-router@6.19.0
    • @remix-run/router@1.12.0

v6.18.0

Compare Source

Minor Changes
  • Add support for manual fetcher key specification via useFetcher({ key: string }) so you can access the same fetcher instance from different components in your application without prop-drilling (RFC) (#​10960)

    • Fetcher keys are now also exposed on the fetchers returned from useFetchers so that they can be looked up by key
  • Add navigate/fetcherKey params/props to useSumbit/Form to support kicking off a fetcher submission under the hood with an optionally user-specified key (#​10960)

    • Invoking a fetcher in this way is ephemeral and stateless
    • If you need to access the state of one of these fetchers, you will need to leverage useFetcher({ key }) to look it up elsewhere
Patch Changes
  • Adds a fetcher context to RouterProvider that holds completed fetcher data, in preparation for the upcoming future flag that will change the fetcher persistence/cleanup behavior (#​10961)
  • Fix the future prop on BrowserRouter, HashRouter and MemoryRouter so that it accepts a Partial<FutureConfig> instead of requiring all flags to be included. (#​10962)
  • Updated dependencies:
    • @remix-run/router@1.11.0
    • react-router@6.18.0

v6.17.0

Compare Source

Minor Changes
  • Add experimental support for the View Transitions API via document.startViewTransition to enable CSS animated transitions on SPA navigations in your application. (#​10916)

    The simplest approach to enabling a View Transition in your React Router app is via the new <Link unstable_viewTransition> prop. This will cause the navigation DOM update to be wrapped in document.startViewTransition which will enable transitions for the DOM update. Without any additional CSS styles, you'll get a basic cross-fade animation for your page.

    If you need to apply more fine-grained styles for your animations, you can leverage the unstable_useViewTransitionState hook which will tell you when a transition is in progress and you can use that to apply classes or styles:

    function ImageLink(to, src, alt) {
      let isTransitioning = unstable_useViewTransitionState(to);
      return (
        <Link to={to} unstable_viewTransition>
          <img
            src={src}
            alt={alt}
            style={{
              viewTransitionName: isTransitioning ? "image-expand" : "",
            }}
          />
        </Link>
      );
    }
    

    You can also use the <NavLink unstable_viewTransition> shorthand which will manage the hook usage for you and automatically add a transitioning class to the <a> during the transition:

    a.transitioning img {
      view-transition-name: "image-expand";
    }
    
    <NavLink to={to} unstable_viewTransition>
      <img src={src} alt={alt} />
    </NavLink>
    

    For an example usage of View Transitions with React Router, check out our fork of the Astro Records demo.

    For more information on using the View Transitions API, please refer to the Smooth and simple transitions with the View Transitions API guide from the Google Chrome team.

    Please note, that because the ViewTransition API is a DOM API, we now export a specific RouterProvider from react-router-dom with this functionality. If you are importing RouterProvider from react-router, then it will not support view transitions. (#​10928

Patch Changes
  • Log a warning and fail gracefully in ScrollRestoration when sessionStorage is unavailable (#​10848)
  • Updated dependencies:
    • @remix-run/router@1.10.0
    • react-router@6.17.0

v6.16.0

Compare Source

Minor Changes
  • Updated dependencies:
    • @remix-run/router@1.9.0
    • react-router@6.16.0
Patch Changes
  • Properly encode rendered URIs in server rendering to avoid hydration errors (#​10769)

v6.15.0

Compare Source

Minor Changes
  • Add's a new redirectDocument() function which allows users to specify that a redirect from a loader/action should trigger a document reload (via window.location) instead of attempting to navigate to the redirected location via React Router (#​10705)
Patch Changes
  • Fixes an edge-case affecting web extensions in Firefox that use URLSearchParams and the useSearchParams hook. (#​10620)
  • Do not include hash in useFormAction() for unspecified actions since it cannot be determined on the server and causes hydration issues (#​10758)
  • Reorder effects in unstable_usePrompt to avoid throwing an exception if the prompt is unblocked and a navigation is performed synchronously (#​10687, #​10718)
  • Updated dependencies:
    • @remix-run/router@1.8.0
    • react-router@6.15.0

v6.14.2

Compare Source

Patch Changes
  • Properly decode element id when emulating hash scrolling via <ScrollRestoration> (#​10682)
  • Add missing <Form state> prop to populate history.state on submission navigations (#​10630)
  • Support proper hydration of Error subclasses such as ReferenceError/TypeError (#​10633)
  • Updated dependencies:
    • @remix-run/router@1.7.2
    • react-router@6.14.2

v6.14.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@6.14.1
    • @remix-run/router@1.7.1

v6.14.0

Compare Source

Minor Changes
  • Add support for application/json and text/plain encodings for useSubmit/fetcher.submit. To reflect these additional types, useNavigation/useFetcher now also contain navigation.json/navigation.text and fetcher.json/fetcher.text which include the json/text submission if applicable (#​10413)

    // The default behavior will still serialize as FormData
    function Component() {
      let navigation = useNavigation();
      let submit = useSubmit();
      submit({ key: "value" }, { method: "post" });
      // navigation.formEncType => "application/x-www-form-urlencoded"
      // navigation.formData    => FormData instance
    }
    
    async function action({ request }) {
      // request.headers.get("Content-Type") => "application/x-www-form-urlencoded"
      // await request.formData()            => FormData instance
    }
    
    // Opt-into JSON encoding with `encType: "application/json"`
    function Component() {
      let navigation = useNavigation();
      let submit = useSubmit();
      submit({ key: "value" }, { method: "post", encType: "application/json" });
      // navigation.formEncType => "application/json"
      // navigation.json        => { key: "value" }
    }
    
    async function action({ request }) {
      // request.headers.get("Content-Type") => "application/json"
      // await request.json()                => { key: "value" }
    }
    
    // Opt-into text encoding with `encType: "text/plain"`
    function Component() {
      let navigation = useNavigation();
      let submit = useSubmit();
      submit("Text submission", { method: "post", encType: "text/plain" });
      // navigation.formEncType => "text/plain"
      // navigation.text        => "Text submission"
    }
    
    async function action({ request }) {
      // request.headers.get("Content-Type") => "text/plain"
      // await request.text()                => "Text submission"
    }
    
Patch Changes
  • When submitting a form from a submitter element, prefer the built-in new FormData(form, submitter) instead of the previous manual approach in modern browsers (those that support the new submitter parameter) (#​9865, #​10627)
    • For browsers that don't support it, we continue to just append the submit button's entry to the end, and we also add rudimentary support for type="image" buttons
    • If developers want full spec-compliant support for legacy browsers, they can use the formdata-submitter-polyfill
  • Call window.history.pushState/replaceState before updating React Router state (instead of after) so that window.location matches useLocation during synchronous React 17 rendering (#​10448)
    • ⚠️ However, generally apps should not be relying on window.location and should always reference useLocation when possible, as window.location will not be in sync 100% of the time (due to popstate events, concurrent mode, etc.)
  • Fix tsc --skipLibCheck:false issues on React 17 (#​10622)
  • Upgrade typescript to 5.1 (#​10581)
  • Updated dependencies:
    • react-router@6.14.0
    • @remix-run/router@1.7.0

v6.13.0

Compare Source

Minor Changes
  • Move React.startTransition usage behind a future flag to avoid issues with existing incompatible Suspense usages. We recommend folks adopting this flag to be better compatible with React concurrent mode, but if you run into issues you can continue without the use of startTransition until v7. Issues usually boils down to creating net-new promises during the render cycle, so if you run into issues you should either lift your promise creation out of the render cycle or put it behind a useMemo. (#​10596)

    Existing behavior will no longer include React.startTransition:

    <BrowserRouter>
      <Routes>{/*...*/}</Routes>
    </BrowserRouter>
    
    <RouterProvider router={router} />
    

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

    <BrowserRouter future={{ v7_startTransition: true }}>
      <Routes>{/*...*/}</Routes>
    </BrowserRouter>
    
    <RouterProvider router={router} future={{ v7_startTransition: true }}/>
    
Patch Changes
  • Work around webpack/terser React.startTransition minification bug in production mode (#​10588)
  • Updated dependencies:
    • react-router@6.13.0

v6.12.1

Compare Source

!WARNING]
Please use version `6.13.0` or later instead of `6.12.1`. This version suffers from a `webpack`/`terser` minification issue resulting in invalid minified code in your resulting production bundles which can cause issues in your application. See [#&#8203;10579](https://github.com/remix-run/react-router/issues/10579) for more details.
Patch Changes
  • Adjust feature detection of React.startTransition to fix webpack + react 17 compilation error (#​10569)
  • Updated dependencies:
    • react-router@6.12.1

v6.12.0

Compare Source

Minor Changes
  • Wrap internal router state updates with React.startTransition if it exists (#​10438)
Patch Changes
  • Re-throw DOMException (DataCloneError) when attempting to perform a PUSH navigation with non-serializable state. (#​10427)
  • Updated dependencies:
    • @remix-run/router@1.6.3
    • react-router@6.12.0

v6.11.2

Compare Source

Patch Changes
  • Export SetURLSearchParams type (#​10444)
  • Updated dependencies:
    • react-router@6.11.2
    • @remix-run/router@1.6.2

v6.11.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@6.11.1
    • @remix-run/router@1.6.1

v6.11.0

Compare Source

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'))
Patch Changes
  • 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 footguns in useEffect calls. (#​10377, #​10409)
  • Add static prop to StaticRouterProvider's internal Router component (#​10401)
  • 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(). When using BrowserRouter, these hooks remain unstable across location changes because they still rely on useLocation(). (#​10336)
  • Updated dependencies:
    • react-router@6.11.0
    • @remix-run/router@1.6.0

v6.10.0

Compare Source

Minor Changes
  • Added support for Future Flags in React Router. The first 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() behavior. (#​10207)

    • When future.v7_normalizeFormMethod === 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)
  • Updated dependencies:
    • @remix-run/router@1.5.0
    • react-router@6.10.0

v6.9.0

Compare Source

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.

    🙌 Huge thanks to @​rossipedia for the Initial Proposal and POC Implementation.

  • Updated dependencies:

    • react-router@6.9.0
    • @remix-run/router@1.4.0

v6.8.2

Compare Source

Patch Changes
  • Treat same-origin absolute URLs in <Link to> as external if they are outside of the router basename (#​10135)
  • Fix useBlocker to return IDLE_BLOCKER during SSR (#​10046)
  • Fix SSR of absolute <Link to> urls (#​10112)
  • Properly escape HTML characters in StaticRouterProvider serialized hydration data (#​10068)
  • Updated dependencies:
    • @remix-run/router@1.3.3
    • react-router@6.8.2

v6.8.1

Compare Source

Patch Changes
  • 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)
  • Updated dependencies:
    • react-router@6.8.1
    • @remix-run/router@1.3.2

v6.8.0

Compare Source

Minor Changes
  • Support absolute URLs in <Link to>. If the URL is for the current origin, it will still do a client-side navigation. If the URL is for a different origin then it will do a fresh document request for the new origin. (#​9900)

    <Link to="https://neworigin.com/some/path">    {/* Document request */}
    <Link to="//neworigin.com/some/path">          {/* Document request */}
    <Link to="https://www.currentorigin.com/path"> {/* Client-side navigation */}
    
Patch Changes
  • Fix bug with search params removal via useSearchParams (#​9969)
  • Respect preventScrollReset on <fetcher.Form> (#​9963)
  • Fix navigation for hash routers on manual URL changes (#​9980)
  • Use pagehide instead of beforeunload for <ScrollRestoration>. This has better cross-browser support, specifically on Mobile Safari. (#​9945)
  • Updated dependencies:
    • @remix-run/router@1.3.1
    • react-router@6.8.0

v6.7.0

Compare Source

Minor Changes
  • Add unstable_useBlocker hook for blocking navigations within the app's location origin (#​9709)
  • Add unstable_usePrompt hook for blocking navigations within the app's location origin (#​9932)
  • Add preventScrollReset prop to <Form> (#​9886)
Patch Changes
  • Added pass-through event listener options argument to useBeforeUnload (#​9709)
  • Streamline jsdom bug workaround in tests (#​9824)
  • Updated dependencies:
    • @remix-run/router@1.3.0
    • react-router@6.7.0

v6.6.2

Compare Source

Patch Changes
  • Ensure useId consistency during SSR (#​9805)
  • Updated dependencies:
    • react-router@6.6.2

v6.6.1

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.2.1
    • react-router@6.6.1

v6.6.0

Compare Source

Minor Changes
  • Add useBeforeUnload() hook (#​9664)
  • Remove unstable_ prefix from createStaticHandler/createStaticRouter/StaticRouterProvider (#​9738)
Patch Changes
  • Proper hydration of Error objects from StaticRouterProvider (#​9664)
  • Support uppercase <Form method> and useSubmit method values (#​9664)
  • Skip initial scroll restoration for SSR apps with hydrationData (#​9664)
  • Fix <button formmethod> form submission overriddes (#​9664)
  • Updated dependencies:
    • @remix-run/router@1.2.0
    • react-router@6.6.0

v6.5.0

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@6.5.0
    • @remix-run/router@1.1.0

v6.4.5

Compare Source

Patch Changes
  • Updated dependencies:
    • @remix-run/router@1.0.5
    • react-router@6.4.5

v6.4.4

Compare Source

Patch Changes
  • Fix issues with encoded characters in NavLink and descendant <Routes> (#​9589, #​9647)
  • Properly serialize/deserialize ErrorResponse instances when using built-in hydration (#​9593)
  • Support basename in static data routers (#​9591)
  • Updated dependencies:
    • @remix-run/router@1.0.4
    • react-router@6.4.4

v6.4.3

Compare Source

Patch Changes
  • Fix hrefs generated for createHashRouter (#​9409)
  • fix encoding/matching issues with special chars (#​9477, #​9496)
  • Properly support index routes with a path in useResolvedPath (#​9486)
  • Respect relative=path prop on NavLink (#​9453)
  • Fix NavLink behavior for root urls (#​9497)
  • Updated dependencies:
    • @remix-run/router@1.0.3
    • react-router@6.4.3

v6.4.2

Compare Source

Patch Changes
  • Respect basename in useFormAction (#​9352)
  • Enhance console error messages for invalid usage of data router hooks (#​9311)
  • If an index route has children, it will result in a runtime error. We have strengthened our RouteObject/RouteProps types to surface the error in TypeScript. (#​9366)
  • Updated dependencies:
    • react-router@6.4.2
    • @remix-run/router@1.0.2

v6.4.1

Compare Source

Patch Changes
  • Updated dependencies:
    • react-router@6.4.1
    • @remix-run/router@1.0.1

v6.4.0

Compare Source

Whoa this is a big one! 6.4.0 brings all the data loading and mutation APIs over from Remix. Here's a quick high level overview, but it's recommended you go check out the docs, especially the feature overview and the tutorial.

New APIs

  • Create your router with createMemoryRouter/createBrowserRouter/createHashRouter
  • Render your router with <RouterProvider>
  • Load data with a Route loader and mutate with a Route action
  • Handle errors with Route errorElement
  • Submit data with the new <Form> component
  • Perform in-page data loads and mutations with useFetcher()
  • Defer non-critical data with defer and Await
  • Manage scroll position with <ScrollRestoration>

New Features

  • Perform path-relative navigations with <Link relative="path"> (#​9160)

Bug Fixes

  • Path resolution is now trailing slash agnostic (#​8861)
  • useLocation returns the scoped location inside a <Routes location> component (#​9094)
  • respect the <Link replace> prop if it is defined (#​8779)

Updated Dependencies

  • react-router@6.4.0

v6.3.0: react-router@v6.3.0

Compare Source

What's Changed
New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.2.2...v6.3.0

v6.2.2

Compare Source

What's Changed

🐛 Bug Fixes
  • Fixed nested splat routes that begin with special URL-safe characters (#​8563)
  • Fixed a bug where index routes were missing route context in some cases (#​8497)

New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.2.1...v6.2.2

v6.2.1

Compare Source

This release updates the internal history dependency to 5.2.0.

Full Changelog: https://github.com/remix-run/react-router/compare/v6.2.0...v6.2.1

v6.2.0

Compare Source

🐛 Bug fixes
  • Fixed the RouteProps element type, which should be a ReactNode (#​8473)
  • Fixed a bug with useOutlet for top-level routes (#​8483)
Features
  • We now use statically analyzable CJS exports. This enables named imports in Node ESM scripts (See the commit).
New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.1.1...v6.2.0

v6.1.1

Compare Source

In v6.1.0 we inadvertently shipped a new, undocumented API that will likely introduce bugs (#​7586). We have flagged HistoryRouter as unstable_HistoryRouter, as this API will likely need to change before a new major release.

Full Changelog: https://github.com/remix-run/react-router/compare/v6.1.0...v6.1.1

v6.1.0

Compare Source

🐛 Bug fixes
  • Fixed a bug that broke support for base64 encoded IDs on nested routes (#​8291)
Features
  • <Outlet> can now receive a context prop. This value is passed to child routes and is accessible via the new useOutletContext hook. See the API docs for details. (#​8461)
  • <NavLink> can now receive a child function for access to its props. (#​8164)
💅 Enhancements
  • Improved TypeScript signature for useMatch and matchPath. For example, when you call useMatch("foo/:bar/:baz"), the path is parsed and the return type will be PathMatch<"bar" | "baz">. (#​8030)
  • A few error message improvements (#​8202)
New Contributors

Full Changelog: https://github.com/remix-run/react-router/compare/v6.0.1...v6.1.0

v6.0.2

Compare Source

Features
  • Added the reloadDocument prop to <Link>. This allows <Link> to function like a normal anchor tag by reloading the document after navigation while maintaining the relative to resolution.
🗒️ Docs
  • Fixed several issues in docblocks and the docs themselves. See the full changelog for the deets!
🤝 New Contributors
Full Changelog

v6.0.1

Compare Source

🐛 Bug Fixes
  • Add a default <StaticRouter location> value (#​8243)
  • Add invariant for using <Route> inside <Routes> to help people make the change (#​8238)

v6.0.0

Compare Source

React Router v6 is here!

Please go read our blog post for more information on all the great stuff in v6 including notes about how to upgrade from React Router v5 and Reach Router.

v6.0.0-beta.8

Compare Source

Remember last week when we said

We anticipate this will be the last beta release before v6 stable next week.

Yeah, about that … 😅

We found and squashed a few high-priority bugs that needed to be addressed first. But it's coming very soon, we promise! In the mean time, here's what you'll get from our eight-est and greatest beta release:

🐛 Bug Fixes
  • We fixed a few bugs in useHref that resulted in the incorrect resolved value in cases where a basename is used on the <Router /> component (See #​8133 and #​8142 for details).
  • We also fixed a bug in our path ranking algorithm so that splat routes (routes with a * path value) are now correctly ranked ahead of layout routes.
🗒️ Docs

We've added lots of goodies to our docs and examples, and there's a lot more yet to come. Take a look and see if you find something that makes your work a little easier! We think the lazy loading and custom query parsing examples are particularly cool! 🤓

v6.0.0-beta.7

Compare Source

In this release we made a small but significant change to how <Link to=".."> works. This is going to help out a lot if you were trying to use links in a * route.

We have also backed out our blocking/prompt APIs for the stable v6 release. We will revisit this post 6.0 when we have a little more time to get it right.

Features

The major change in this release could also be classified as a bugfix or a breaking change, depending on how you look at it. We essentialy altered the way <Link to=".."> works. See #​8086 for the motivation behind this change.

You'll probably want to reread the section in the v5 => v6 migration guide about <Link to> values (it has been updated), but it basically boils down to this: any leading .. segment in a <Link to> value traverses "up" one route and builds upon that route's path instead of just removing one URL segment. This feature really completes the story of relative routes and links.

We could consider this a bugfix, since this is how it was always intended to work in the first place. Without it, you'd have a difficult time linking predictably in * routes because your <a href> would be different depending on the number of segments in the current URL.

The reason this could also be considered a breaking change is that .. now works slightly differently in <Link to> than it would in <a href>. When you have <a href=".."> it operates on the URL pathname, removing one segment of the current URL. However, since many routes really only match a single segment of the URL, there is often no difference between <Link to=".."> and <a href="..">.

💔 Breaking Changes
  • We removed useBlocker(), usePrompt(), and <Prompt> for now. We will revisit these post 6.0 when we have more time to get it right. But we don't want it to block (see what I did there) the release of all the other awesome stuff we've got in v6.
🛠 Roadmap

We anticipate this will be the last beta release before v6 stable next week. Please give it a shot and let us know how it goes!

👍 Upgrading

If you're thinking about upgrading to v6, I published a few notes this past week that may help you:

Both of those posts contain steps you can take today in your v5 app without upgrading to v6.

We are also developing a backwards compat lib that should help some of you upgrade from v5 to v6. We'll post more about this when it's ready.

💻 Installing

Development for v6 has switched from dev to the main branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.6

Compare Source

No big enhancements in this release, just squashing bugs and writing lots of tests! Also, we are hard at work on cranking out examples for v6. See the end of this post for an update on our roadmap between here and v6 stable.

🧰 Examples

We have begun creating some examples for v6 that we hope will help developers make effective use of all the new features we have. So far, we have examples for the following:

  • Basic Example – A basic client-side app for v6 showing how to use nested routes, layouts, links, and the new <Outlet> API
  • Auth Example – Demonstrates an authentication flow including using the new useNavigate() hook, the <Navigate> element, and location.state
  • Search Params Example – Demonstrates how to build a simple search form that uses the new useSearchParams() hook
  • SSR Example – A server-rendered app that uses <StaticRouter> on the server and uses a <BrowserRouter> with ReactDOM.hydrate() on the client

Each example includes a button in the README that allows you to instantly launch a running instance on StackBlitz that you can play with. We hope you enjoy exploring!

🐛 Bugfixes
  • Make <NavLink> match only whole URL segments instead of pieces. This means that <NavLink to="/home/users"> will still be active at /home/users, but not at /home/users2. See #​7523
  • Makes "layout routes" (routes with no path) never match unless one of their children do. See #​8085
  • Fixes a route matching regression with splat routes that was introduced in beta.5. See #​8072 and #​8109
  • Fixes matching a nested splat route. See af7d038
  • Provide all parent route params to descendant <Routes>. This reverses a decision that we made in beta.5 to remove them. See #​8073
💔 Breaking Changes
  • Splats in route paths (*) match only after a / in the URL. This means that <Route path="files*"> will always match as if it were <Route path="files/*">. The router will issue a warning if your route path ends with * but not /*
🛠 Roadmap

We are very close to a stable release! The last big code changes we need to make are:

  • Fixing "linking up". Currently a <Link to=".."> operates on the URL pathname. However, this makes it difficult to link to the parent route when you're in a splat route. See #​8086. This will be a breaking change.
  • We are going to remove useBlocker() and <Prompt> in our initial v6 release, with plans to revisit them and possibly add them back at some point in the future. I still need to write up something here that explains our rationale. This will also be a breaking change.
  • We are going to add some animation primitives (see https://github.com/remix-run/react-router/discussions/8008). The <Routes location> prop will be in v6, but it isn't ideal for animation.
💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.5

Compare Source

This week's release adds some much-needed polish to a few niche features of the router: splat routes (a route that uses a * path) and basenames. It also adds a renderMatches API that completes the story for those of you who may have been using react-router-config in v4 and v5.

🐛 Bugfixes
  • A * in a child route path matches after a slash following its parent route path. This fixes some situations where the * was overly greedy (see #​7972)
  • Resolution of <Link to="."> and useResolvedPath(".") values are fixed in splat routes. Previously these resolved relative to the parent route's path. They now resolve relative to the path of the route that rendered them.
Enhancements

This release makes it easier to work with apps that have multiple entry points. Using the <Router basename> prop allows React Router to be easily deployed on only a portion of a larger site by using a portion of the URL pathname (the "basename") to transparently prefix all route paths and link navigations.

For example, you can deploy one React Router app at the /inbox URL prefix, and another one at the /admin prefix. These base URLs represent two different entry points into your app, each with its own bundles. The rest of your site, including the root / URL could be rendered by something other than React Router, for example by your server framework of choice.

In the bundle for each entry point, simply initialize React Router with the basename of that entry point.

<Router basename="/inbox">
  // ...
</Router>

Then define your routes and link paths without using the /inbox URL prefix in any of them. The entire app will run relative to that prefix.

Another improvement in this release is the addition of the renderMatches API, which is the complement of matchRoutes. These APIs are both very low-level and should not normally be needed. But they are sometimes nice to use if you are doing your own data loading using the array of matches that you get back from matchRoutes.

matchRoutes and renderMatches are the equivalent of the react-router-config package we shipped in v4 and v5, just built directly into the router instead of in a separate package.

💔 Breaking Changes
  • <Routes basename> has moved to <Router basename>. This prop is also available on all router variants (<BrowserRouter>, <HashRouter>, etc.).
  • useLocation().pathname no longer includes the basename, if present.
  • The basename argument was removed from useRoutes. This reverts the signature to useRoutes(routes, location), same as it was previous to beta.4.
  • Descendant <Routes> do not get the params from their parents. This helps a set of <Routes> to be more portable by decoupling it from the params of its parents and makes it easier to know which params will be returned from useParams(). If you were relying on this behavior previously, you'll need to pass along the params manually to the elements rendered by the descendant <Routes>. See this comment for an example of how this is to be done and for a potential workaround if you really need the old behavior.
  • match.pathname in a splat route now includes the portion of the pathname matched by the *. This makes the * param behave much more like other dynamic :id-style params.
  • Resolution of relative <Link>s in splat routes is changed now because the entire pathname that was matched by that route is now different (see previous bullet). Instead of resolving relative to the portion of the pathname before the *, paths resolve relative to the full pathname that was matched by the route.
💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.4

Compare Source

Last week we released a lot of nice little bug features, but we did get a little carried away and let a little bug slip through with relative path resolution. Our bad! That nasty lil' guy is squashed in this week's beta. 🐛

And there's more! Let's dive in…

🐛 Bugfixes
  • Path resolution for nested relative routes was broken in the last release and should now be fixed. Nested routes construct their pathname based on the location of their parent, not the current location. This is explained in detail under Relative Routes and Links in our advanced guides, and the issue itself in #​8004
Enhancements
  • We made some enhancements with the Params type which is now generic, so you can add your own types if you know what to expect from functions that return query parameters. (#​8019)
// before
let { valid, invalid } = useParams(); // No problems here!

let match = useMatch("profile/:userId");
let userId = match?.params.user; // wrong param, but TS doesn't know that!

// after:
let { valid, invalid } = useParams<"valid" | "key">(); // Property 'invalid' does not exist on type 'Params<"valid" | "key">'

let match = useMatch<"userId">("profile/:userId");
let userId = match?.params.user; // Property 'user' does not exist on type 'Params<"userId">'
  • Absolute nested path support

There was quite a bit of discussion in #​7335 from people who are using constants to define their route paths. In this style, paths are often written as absolute paths from the root / URL. These constants are then able to be used both in <Route path> definitions as well as <Link to> values. It usually looks something like this:

const USERS_PATH = "/users";
const USERS_INDEX_PATH = `${USERS_PATH}/`;
const USER_PROFILE_PATH = `${USERS_PATH}/:id`;

function UsersRoutes() {
  return (
    <Routes>
      <Route path={USERS_PATH} element={<UsersLayout />}>
        <Route path={USERS_INDEX_PATH} element={<UsersIndex />} />
        <Route path={USER_PROFILE_PATH} element={<UserProfile />} />
      </Route>
    </Routes>
  );
}

This style of use is now fully supported in v6. This is great for people who write their apps like this, but it technically could cause some breakage if you were using absolute paths (that start with /) in nested routes in previous betas. To fix this, simply remove the / from the beginning of any route paths that are meant to be relative. React Router will throw an error if you are using absolute paths that don't match their parent route paths. Hopefully this should help you find them if you are upgrading.

If you were using <Route path="/"> to indicate an index route, you can now use the new <Route index> prop to accomplish the same thing. The index prop makes it easy to scan a route config to find the index route. It also provides a guarantee that nobody will ever add children to that route.

Here's the same route config as the one above, but rewritten with relative paths and the index prop:

function UsersRoutes() {
  return (
    <Routes>
      <Route path="users" element={<UsersLayout />}>
        <Route index element={<UsersIndex />} />
        <Route path=":id" element={<UserProfile />} />
      </Route>
    </Routes>
  );
}

A lot of our work on React Router is about doing the least surprising thing for our users. Allowing absolute paths in nested routes gets us a little closer to that goal!

💔 Breaking Changes
  • Removed the ability for nested route paths to begin with a / and not contain the complete path of their parent routes. This was necessary in order to introduce support for absolute paths in nested routes, described in detail above

  • Removed the createRoutesFromArray utility function. You can now pass your routes directly to useRoutes or matchRoutes without passing it through createRoutesFromArray first

  • Removed the PartialRouteObject type. If you were importing and using this type before, use RouteObject instead, which has been updated to make all properties optional

  • The useRoutes API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object:

// Before
useRoutes([...routes], basename);

// After
useRoutes([...routes], { basename });
  • The matchPath function now returns match.pattern instead of match.path, which is a little more descriptive about what it actually is
💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next

v6.0.0-beta.3

Compare Source

Loads of goodies for you this week, as well as a few breaking changes for all of you eager beavers who are brave enough to use beta software in production! 🦫

(seriously, thank you all for helping us tighten up our APIs and fix nasty bugs)

💔 Breaking Changes!
  • NavLink no longer supports the activeClassName or activeStyle props. Instead, we provide a more powerful API that allows you to pass functions to either the className or style props to conditionally apply values based on the link's active state. While a bit more verbose in some cases, this offers a nicer experience for folks who use utility class-based CSS. (#​7194)
// Before
<NavLink className="link" activeClassName="active-link" />
<NavLink style={{ color: "blue" }} activeStyle={{ color: "green" }} />

// After
<NavLink
  className={({ isActive }) =>
    `link ${
      isActive
        ? "active-link"
        : // Couldn't do this before!
          "inactive-link"
    }`
  }
/>
<NavLink style={({ isActive }) => ({ color: isActive ? "green" : "blue" })} />

Note: You can always abstract over this feature in a custom NavLink if you prefer the old v5 API.

  • The useRoutes API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object:
// Before
useRoutes([...routes], basename);

// After
useRoutes([...routes], { basename });
🐛 Bugfixes
  • The basename prop on Routes is treated as case-insensitive (#​7997)
  • useNavigate previously used the incorrect pathname when called from parent routes when the URL matches one of its children. This fix also applies to useSearchParams (#​7880)
Enhancements
  • Routes and useRoutes now allow you to override the location, which may be useful when building some modal interfaces and route transition animations. We are working hard to update our docs to include examples for advanced patterns where this might be useful, but in the mean time this also brings Routes closer to feature parity with v5's Switch via the location prop. (#​7117)
  • Provided new hooks useClickHandler and usePressHandler to make customizing Links a bit easier. (#​7998)
    • Please note: with great power comes great responsibility. If you create a custom Link, be sure to render an actual HTML anchor element, otherwise your app will likely be inaccessible without a significant amount of additional work which, I assure you, you don't want to do!
💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next
🙏 Credits

Thanks to @​andrelandgraf, @​dhulme, @​fgatti675, @​hugmanrique, @​MeiKatz, @​chaance and @​mjackson for your contributions!

v6.0.0-beta.2

Compare Source

🐛 Bugfixes
Enhancements
💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next
🙏 Credits

Thanks to @​liho98, @​wojtekmaj, @​cravend, @​chaance and @​mjackson for your contributions!

Enjoy!

v6.0.0-beta.1

Compare Source

We're on the road to a stable v6 release!

There are no new features in this release since beta.0, but a handful of squashed bugs, perf enhancements, and DX improvements for TypeScript users.

🐛 Bugfixes
Enhancements
  • Internally we are separating navigator into a separate context object, meaning your components that call useNavigate will probably render a little less often. Wowza, much perf!
  • react-router-dom and react-router-native now re-exports all types exported from react-router
💻 Installing

Development for v6 is chugging along on the dev branch.

If you'd like to test it out, install from npm:

$ npm install history react-router-dom@next
🙏 Credits

Thanks to @​brookslybrand, @​bogdansoare, @​chaance and @​mjackson for your contributions!

Enjoy!


Configuration

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

🚦 Automerge: Enabled.

Rebasing: Whenever PR becomes conflicted, 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) | dependencies | minor | [`6.0.0-beta.0` -> `6.22.3`](https://renovatebot.com/diffs/npm/react-router/6.0.0-beta.0/6.22.3) | | [react-router-dom](https://github.com/remix-run/react-router) | dependencies | minor | [`6.0.0-beta.0` -> `6.22.3`](https://renovatebot.com/diffs/npm/react-router-dom/6.0.0-beta.0/6.22.3) | --- ### Release Notes <details> <summary>remix-run/react-router (react-router)</summary> ### [`v6.22.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6223) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.22.2...react-router@6.22.3) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.15.3` ### [`v6.22.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6222) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.22.1...react-router@6.22.2) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.15.2` ### [`v6.22.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6221) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.22.0...react-router@6.22.1) ##### Patch Changes - Fix encoding/decoding issues with pre-encoded dynamic parameter values ([#&#8203;11199](https://github.com/remix-run/react-router/pull/11199)) - Updated dependencies: - `@remix-run/router@1.15.1` ### [`v6.22.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6220) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.21.3...react-router@6.22.0) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.15.0` ### [`v6.21.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6213) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.21.2...react-router@6.21.3) ##### Patch Changes - Remove leftover `unstable_` prefix from `Blocker`/`BlockerFunction` types ([#&#8203;11187](https://github.com/remix-run/react-router/pull/11187)) ### [`v6.21.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6212) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.21.1...react-router@6.21.2) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.14.2` ### [`v6.21.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6211) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.21.0...react-router@6.21.1) ##### Patch Changes - Fix bug with `route.lazy` not working correctly on initial SPA load when `v7_partialHydration` is specified ([#&#8203;11121](https://github.com/remix-run/react-router/pull/11121)) - Updated dependencies: - `@remix-run/router@1.14.1` ### [`v6.21.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6210) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.20.1...react-router@6.21.0) ##### Minor Changes - Add a new `future.v7_relativeSplatPath` flag to implement a breaking bug fix to relative routing when inside a splat route. ([#&#8203;11087](https://github.com/remix-run/react-router/pull/11087)) This fix was originally added in [#&#8203;10983](https://github.com/remix-run/react-router/issues/10983) and was later reverted in [#&#8203;11078](https://github.com/remix-run/react-router/pull/11078) because it was determined that a large number of existing applications were relying on the buggy behavior (see [#&#8203;11052](https://github.com/remix-run/react-router/issues/11052)) **The Bug** The buggy behavior is that without this flag, the default behavior when resolving relative paths is to *ignore* any splat (`*`) portion of the current route path. **The Background** This decision was originally made thinking that it would make the concept of nested different sections of your apps in `<Routes>` easier if relative routing would *replace* the current splat: ```jsx <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="dashboard/*" element={<Dashboard />} /> </Routes> </BrowserRouter> ``` Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects` will match the `Dashboard` route. The dashboard component itself can then render nested `<Routes>`: ```jsx function Dashboard() { return ( <div> <h2>Dashboard</h2> <nav> <Link to="/">Dashboard Home</Link> <Link to="team">Team</Link> <Link to="projects">Projects</Link> </nav> <Routes> <Route path="/" element={<DashboardHome />} /> <Route path="team" element={<DashboardTeam />} /> <Route path="projects" element={<DashboardProjects />} /> </Routes> </div> ); } ``` Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the `Dashboard` as its own independent app, or embed it into your large app without making any changes to it. **The Problem** The problem is that this concept of ignoring part of a path breaks a lot of other assumptions in React Router - namely that `"."` always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using `"."`: ```jsx // If we are on URL /dashboard/team, and we want to link to /dashboard/team: function DashboardTeam() { // ❌ This is broken and results in <a href="/dashboard"> return <Link to=".">A broken link to the Current URL</Link>; // ✅ This is fixed but super unintuitive since we're already at /dashboard/team! return <Link to="./team">A broken link to the Current URL</Link>; } ``` We've also introduced an issue that we can no longer move our `DashboardTeam` component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as `/dashboard/:widget`. Now, our `"."` links will, properly point to ourself *inclusive of the dynamic param value* so behavior will break from it's corresponding usage in a `/dashboard/*` route. Even worse, consider a nested splat route configuration: ```jsx <BrowserRouter> <Routes> <Route path="dashboard"> <Route path="*" element={<Dashboard />} /> </Route> </Routes> </BrowserRouter> ``` Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard` component go to the same place! That is definitely not correct! Another common issue arose in Data Routers (and Remix) where any `<Form>` should post to it's own route `action` if you the user doesn't specify a form action: ```jsx let router = createBrowserRouter({ path: "/dashboard", children: [ { path: "*", action: dashboardAction, Component() { // ❌ This form is broken! It throws a 405 error when it submits because // it tries to submit to /dashboard (without the splat value) and the parent // `/dashboard` route doesn't have an action return <Form method="post">...</Form>; }, }, ], }); ``` This is just a compounded issue from the above because the default location for a `Form` to submit to is itself (`"."`) - and if we ignore the splat portion, that now resolves to the parent route. **The Solution** If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage `../` for any links to "sibling" pages: ```jsx <BrowserRouter> <Routes> <Route path="dashboard"> <Route index path="*" element={<Dashboard />} /> </Route> </Routes> </BrowserRouter> function Dashboard() { return ( <div> <h2>Dashboard</h2> <nav> <Link to="..">Dashboard Home</Link> <Link to="../team">Team</Link> <Link to="../projects">Projects</Link> </nav> <Routes> <Route path="/" element={<DashboardHome />} /> <Route path="team" element={<DashboardTeam />} /> <Route path="projects" element={<DashboardProjects />} /> </Router> </div> ); } ``` This way, `.` means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and `..` always means "my parents pathname". ##### Patch Changes - Properly handle falsy error values in ErrorBoundary's ([#&#8203;11071](https://github.com/remix-run/react-router/pull/11071)) - Updated dependencies: - `@remix-run/router@1.14.0` ### [`v6.20.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6201) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.20.0...react-router@6.20.1) ##### Patch Changes - Revert the `useResolvedPath` fix for splat routes due to a large number of applications that were relying on the buggy behavior (see [#&#8203;11052 (comment)](https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329)). We plan to re-introduce this fix behind a future flag in the next minor version. ([#&#8203;11078](https://github.com/remix-run/react-router/pull/11078)) - Updated dependencies: - `@remix-run/router@1.13.1` ### [`v6.20.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6200) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.19.0...react-router@6.20.0) ##### Minor Changes - Export the `PathParam` type from the public API ([#&#8203;10719](https://github.com/remix-run/react-router/pull/10719)) ##### Patch Changes - Fix bug with `resolveTo` in splat routes ([#&#8203;11045](https://github.com/remix-run/react-router/pull/11045)) - This is a follow up to [#&#8203;10983](https://github.com/remix-run/react-router/pull/10983) to handle the few other code paths using `getPathContributingMatches` - This removes the `UNSAFE_getPathContributingMatches` export from `@remix-run/router` since we no longer need this in the `react-router`/`react-router-dom` layers - Updated dependencies: - `@remix-run/router@1.13.0` ### [`v6.19.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6190) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.18.0...react-router@6.19.0) ##### Minor Changes - Add `unstable_flushSync` option to `useNavigate`/`useSumbit`/`fetcher.load`/`fetcher.submit` to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#&#8203;11005](https://github.com/remix-run/react-router/pull/11005)) - Remove the `unstable_` prefix from the [`useBlocker`](https://reactrouter.com/en/main/hooks/use-blocker) hook as it's been in use for enough time that we are confident in the API. We do not plan to remove the prefix from `unstable_usePrompt` due to differences in how browsers handle `window.confirm` that prevent React Router from guaranteeing consistent/correct behavior. ([#&#8203;10991](https://github.com/remix-run/react-router/pull/10991)) ##### Patch Changes - Fix `useActionData` so it returns proper contextual action data and not *any* action data in the tree ([#&#8203;11023](https://github.com/remix-run/react-router/pull/11023)) - Fix bug in `useResolvedPath` that would cause `useResolvedPath(".")` in a splat route to lose the splat portion of the URL path. ([#&#8203;10983](https://github.com/remix-run/react-router/pull/10983)) - ⚠️ This fixes a quite long-standing bug specifically for `"."` paths inside a splat route which incorrectly dropped the splat portion of the URL. If you are relative routing via `"."` inside a splat route in your application you should double check that your logic is not relying on this buggy behavior and update accordingly. - Updated dependencies: - `@remix-run/router@1.12.0` ### [`v6.18.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6180) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.17.0...react-router@6.18.0) ##### Patch Changes - Fix the `future` prop on `BrowserRouter`, `HashRouter` and `MemoryRouter` so that it accepts a `Partial<FutureConfig>` instead of requiring all flags to be included. ([#&#8203;10962](https://github.com/remix-run/react-router/pull/10962)) - Updated dependencies: - `@remix-run/router@1.11.0` ### [`v6.17.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6170) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.16.0...react-router@6.17.0) ##### Patch Changes - Fix `RouterProvider` `future` prop type to be a `Partial<FutureConfig>` so that not all flags must be specified ([#&#8203;10900](https://github.com/remix-run/react-router/pull/10900)) - Updated dependencies: - `@remix-run/router@1.10.0` ### [`v6.16.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6160) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.15.0...react-router@6.16.0) ##### Minor Changes - In order to move towards stricter TypeScript support in the future, we're aiming to replace current usages of `any` with `unknown` on exposed typings for user-provided data. To do this in Remix v2 without introducing breaking changes in React Router v6, we have added generics to a number of shared types. These continue to default to `any` in React Router and are overridden with `unknown` in Remix. In React Router v7 we plan to move these to `unknown` as a breaking change. ([#&#8203;10843](https://github.com/remix-run/react-router/pull/10843)) - `Location` now accepts a generic for the `location.state` value - `ActionFunctionArgs`/`ActionFunction`/`LoaderFunctionArgs`/`LoaderFunction` now accept a generic for the `context` parameter (only used in SSR usages via `createStaticHandler`) - The return type of `useMatches` (now exported as `UIMatch`) accepts generics for `match.data` and `match.handle` - both of which were already set to `unknown` - Move the `@private` class export `ErrorResponse` to an `UNSAFE_ErrorResponseImpl` export since it is an implementation detail and there should be no construction of `ErrorResponse` instances in userland. This frees us up to export a `type ErrorResponse` which correlates to an instance of the class via `InstanceType`. Userland code should only ever be using `ErrorResponse` as a type and should be type-narrowing via `isRouteErrorResponse`. ([#&#8203;10811](https://github.com/remix-run/react-router/pull/10811)) - Export `ShouldRevalidateFunctionArgs` interface ([#&#8203;10797](https://github.com/remix-run/react-router/pull/10797)) - Removed private/internal APIs only required for the Remix v1 backwards compatibility layer and no longer needed in Remix v2 (`_isFetchActionRedirect`, `_hasFetcherDoneAnything`) ([#&#8203;10715](https://github.com/remix-run/react-router/pull/10715)) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.9.0` ### [`v6.15.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6150) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.14.2...react-router@6.15.0) ##### Minor Changes - Add's a new `redirectDocument()` function which allows users to specify that a redirect from a `loader`/`action` should trigger a document reload (via `window.location`) instead of attempting to navigate to the redirected location via React Router ([#&#8203;10705](https://github.com/remix-run/react-router/pull/10705)) ##### Patch Changes - Ensure `useRevalidator` is referentially stable across re-renders if revalidations are not actively occurring ([#&#8203;10707](https://github.com/remix-run/react-router/pull/10707)) - Updated dependencies: - `@remix-run/router@1.8.0` ### [`v6.14.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6142) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.14.1...react-router@6.14.2) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.7.2` ### [`v6.14.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6141) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.14.0...react-router@6.14.1) ##### Patch Changes - Fix loop in `unstable_useBlocker` when used with an unstable blocker function ([#&#8203;10652](https://github.com/remix-run/react-router/pull/10652)) - Fix issues with reused blockers on subsequent navigations ([#&#8203;10656](https://github.com/remix-run/react-router/pull/10656)) - Updated dependencies: - `@remix-run/router@1.7.1` ### [`v6.14.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6140) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.13.0...react-router@6.14.0) ##### Patch Changes - Strip `basename` from locations provided to `unstable_useBlocker` functions to match `useLocation` ([#&#8203;10573](https://github.com/remix-run/react-router/pull/10573)) - Fix `generatePath` when passed a numeric `0` value parameter ([#&#8203;10612](https://github.com/remix-run/react-router/pull/10612)) - Fix `unstable_useBlocker` key issues in `StrictMode` ([#&#8203;10573](https://github.com/remix-run/react-router/pull/10573)) - Fix `tsc --skipLibCheck:false` issues on React 17 ([#&#8203;10622](https://github.com/remix-run/react-router/pull/10622)) - Upgrade `typescript` to 5.1 ([#&#8203;10581](https://github.com/remix-run/react-router/pull/10581)) - Updated dependencies: - `@remix-run/router@1.7.0` ### [`v6.13.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6130) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.12.1...react-router@6.13.0) ##### Minor Changes - Move [`React.startTransition`](https://react.dev/reference/react/startTransition) usage behind a [future flag](https://reactrouter.com/en/main/guides/api-development-strategy) to avoid issues with existing incompatible `Suspense` usages. We recommend folks adopting this flag to be better compatible with React concurrent mode, but if you run into issues you can continue without the use of `startTransition` until v7. Issues usually boils down to creating net-new promises during the render cycle, so if you run into issues you should either lift your promise creation out of the render cycle or put it behind a `useMemo`. ([#&#8203;10596](https://github.com/remix-run/react-router/pull/10596)) Existing behavior will no longer include `React.startTransition`: ```jsx <BrowserRouter> <Routes>{/*...*/}</Routes> </BrowserRouter> <RouterProvider router={router} /> ``` If you wish to enable `React.startTransition`, pass the future flag to your component: ```jsx <BrowserRouter future={{ v7_startTransition: true }}> <Routes>{/*...*/}</Routes> </BrowserRouter> <RouterProvider router={router} future={{ v7_startTransition: true }}/> ``` ##### Patch Changes - Work around webpack/terser `React.startTransition` minification bug in production mode ([#&#8203;10588](https://github.com/remix-run/react-router/pull/10588)) ### [`v6.12.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6121) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.12.0...react-router@6.12.1) > \[!WARNING] > Please use version `6.13.0` or later instead of `6.12.1`. This version suffers from a `webpack`/`terser` minification issue resulting in invalid minified code in your resulting production bundles which can cause issues in your application. See [#&#8203;10579](https://github.com/remix-run/react-router/issues/10579) for more details. ##### Patch Changes - Adjust feature detection of `React.startTransition` to fix webpack + react 17 compilation error ([#&#8203;10569](https://github.com/remix-run/react-router/pull/10569)) ### [`v6.12.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6120) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.11.2...react-router@6.12.0) ##### Minor Changes - Wrap internal router state updates with `React.startTransition` if it exists ([#&#8203;10438](https://github.com/remix-run/react-router/pull/10438)) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.6.3` ### [`v6.11.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6112) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.11.1...react-router@6.11.2) ##### Patch Changes - Fix `basename` duplication in descendant `<Routes>` inside a `<RouterProvider>` ([#&#8203;10492](https://github.com/remix-run/react-router/pull/10492)) - Updated dependencies: - `@remix-run/router@1.6.2` ### [`v6.11.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6111) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.11.0...react-router@6.11.1) ##### Patch Changes - Fix usage of `Component` API within descendant `<Routes>` ([#&#8203;10434](https://github.com/remix-run/react-router/pull/10434)) - Fix bug when calling `useNavigate` from `<Routes>` inside a `<RouterProvider>` ([#&#8203;10432](https://github.com/remix-run/react-router/pull/10432)) - Fix usage of `<Navigate>` in strict mode when using a data router ([#&#8203;10435](https://github.com/remix-run/react-router/pull/10435)) - Updated dependencies: - `@remix-run/router@1.6.1` ### [`v6.11.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6110) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.10.0...react-router@6.11.0) ##### Patch Changes - Log loader/action errors to the console in dev for easier stack trace evaluation ([#&#8203;10286](https://github.com/remix-run/react-router/pull/10286)) - Fix bug preventing rendering of descendant `<Routes>` when `RouterProvider` errors existed ([#&#8203;10374](https://github.com/remix-run/react-router/pull/10374)) - Fix inadvertent re-renders when using `Component` instead of `element` on a route definition ([#&#8203;10287](https://github.com/remix-run/react-router/pull/10287)) - 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. ([#&#8203;10394](https://github.com/remix-run/react-router/pull/10394)) - Switched from `useSyncExternalStore` to `useState` for internal `@remix-run/router` router state syncing in `<RouterProvider>`. We found some [subtle bugs](https://codesandbox.io/s/use-sync-external-store-loop-9g7b81) where router state updates got propagated *before* other normal `useState` updates, which could lead to footguns in `useEffect` calls. ([#&#8203;10377](https://github.com/remix-run/react-router/pull/10377), [#&#8203;10409](https://github.com/remix-run/react-router/pull/10409)) - Allow `useRevalidator()` to resolve a loader-driven error boundary scenario ([#&#8203;10369](https://github.com/remix-run/react-router/pull/10369)) - Avoid unnecessary unsubscribe/resubscribes on router state changes ([#&#8203;10409](https://github.com/remix-run/react-router/pull/10409)) - 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()`. When using `BrowserRouter`, these hooks remain unstable across location changes because they still rely on `useLocation()`. ([#&#8203;10336](https://github.com/remix-run/react-router/pull/10336)) - Updated dependencies: - `@remix-run/router@1.6.0` ### [`v6.10.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;6100) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.9.0...react-router@6.10.0) ##### Minor Changes - Added support for [**Future Flags**](https://reactrouter.com/en/main/guides/api-development-strategy) in React Router. The first 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()` behavior. ([#&#8203;10207](https://github.com/remix-run/react-router/pull/10207)) - When `future.v7_normalizeFormMethod === 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 route ID generation when using Fragments in `createRoutesFromElements` ([#&#8203;10193](https://github.com/remix-run/react-router/pull/10193)) - Updated dependencies: - `@remix-run/router@1.5.0` ### [`v6.9.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;690) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.8.2...react-router@6.9.0) ##### 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". ([#&#8203;10045](https://github.com/remix-run/react-router/pull/10045)) **Example JSON Syntax** ```jsx // 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** ```jsx // 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!** ([#&#8203;10045](https://github.com/remix-run/react-router/pull/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. ```jsx // 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: ```jsx 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`](https://github.com/remix-run/react-router/tree/main/examples/lazy-loading-router-provider) directory of the repository. 🙌 Huge thanks to [@&#8203;rossipedia](https://github.com/rossipedia) for the [Initial Proposal](https://github.com/remix-run/react-router/discussions/9826) and [POC Implementation](https://github.com/remix-run/react-router/pull/9830). - Updated dependencies: - `@remix-run/router@1.4.0` ##### Patch Changes - Fix `generatePath` incorrectly applying parameters in some cases ([#&#8203;10078](https://github.com/remix-run/react-router/pull/10078)) - Improve memoization for context providers to avoid unnecessary re-renders ([#&#8203;9983](https://github.com/remix-run/react-router/pull/9983)) ### [`v6.8.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;682) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.8.1...react-router@6.8.2) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.3.3` ### [`v6.8.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;681) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.8.0...react-router@6.8.1) ##### Patch Changes - Remove inaccurate console warning for POP navigations and update active blocker logic ([#&#8203;10030](https://github.com/remix-run/react-router/pull/10030)) - Updated dependencies: - `@remix-run/router@1.3.2` ### [`v6.8.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;680) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.7.0...react-router@6.8.0) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.3.1` ### [`v6.7.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;670) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.6.2...react-router@6.7.0) ##### Minor Changes - Add `unstable_useBlocker` hook for blocking navigations within the app's location origin ([#&#8203;9709](https://github.com/remix-run/react-router/pull/9709)) ##### Patch Changes - Fix `generatePath` when optional params are present ([#&#8203;9764](https://github.com/remix-run/react-router/pull/9764)) - Update `<Await>` to accept `ReactNode` as children function return result ([#&#8203;9896](https://github.com/remix-run/react-router/pull/9896)) - Updated dependencies: - `@remix-run/router@1.3.0` ### [`v6.6.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;662) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.6.1...react-router@6.6.2) ##### Patch Changes - Ensure `useId` consistency during SSR ([#&#8203;9805](https://github.com/remix-run/react-router/pull/9805)) ### [`v6.6.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;661) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.6.0...react-router@6.6.1) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.2.1` ### [`v6.6.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;660) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.5.0...react-router@6.6.0) ##### Patch Changes - Prevent `useLoaderData` usage in `errorElement` ([#&#8203;9735](https://github.com/remix-run/react-router/pull/9735)) - Updated dependencies: - `@remix-run/router@1.2.0` ### [`v6.5.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;650) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.4.5...react-router@6.5.0) This release introduces support for [Optional Route Segments](https://github.com/remix-run/react-router/issues/9546). Now, adding a `?` to the end of any path segment will make that entire segment optional. This works for both static segments and dynamic parameters. **Optional Params Examples** - `<Route path=":lang?/about>` will match: - `/:lang/about` - `/about` - `<Route path="/multistep/:widget1?/widget2?/widget3?">` will match: - `/multistep` - `/multistep/:widget1` - `/multistep/:widget1/:widget2` - `/multistep/:widget1/:widget2/:widget3` **Optional Static Segment Example** - `<Route path="/home?">` will match: - `/` - `/home` - `<Route path="/fr?/about">` will match: - `/about` - `/fr/about` ##### Minor Changes - Allows optional routes and optional static segments ([#&#8203;9650](https://github.com/remix-run/react-router/pull/9650)) ##### Patch Changes - Stop incorrectly matching on partial named parameters, i.e. `<Route path="prefix-:param">`, to align with how splat parameters work. If you were previously relying on this behavior then it's recommended to extract the static portion of the path at the `useParams` call site: ([#&#8203;9506](https://github.com/remix-run/react-router/pull/9506)) ```jsx // Old behavior at URL /prefix-123 <Route path="prefix-:id" element={<Comp /> }> function Comp() { let params = useParams(); // { id: '123' } let id = params.id; // "123" ... } // New behavior at URL /prefix-123 <Route path=":id" element={<Comp /> }> function Comp() { let params = useParams(); // { id: 'prefix-123' } let id = params.id.replace(/^prefix-/, ''); // "123" ... } ``` - Updated dependencies: - `@remix-run/router@1.1.0` ### [`v6.4.5`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;645) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.4.4...react-router@6.4.5) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.0.5` ### [`v6.4.4`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;644) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.4.3...react-router@6.4.4) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.0.4` ### [`v6.4.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;643) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.4.2...react-router@6.4.3) ##### Patch Changes - `useRoutes` should be able to return `null` when passing `locationArg` ([#&#8203;9485](https://github.com/remix-run/react-router/pull/9485)) - fix `initialEntries` type in `createMemoryRouter` ([#&#8203;9498](https://github.com/remix-run/react-router/pull/9498)) - Updated dependencies: - `@remix-run/router@1.0.3` ### [`v6.4.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;642) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.4.1...react-router@6.4.2) ##### Patch Changes - Fix `IndexRouteObject` and `NonIndexRouteObject` types to make `hasErrorElement` optional ([#&#8203;9394](https://github.com/remix-run/react-router/pull/9394)) - Enhance console error messages for invalid usage of data router hooks ([#&#8203;9311](https://github.com/remix-run/react-router/pull/9311)) - If an index route has children, it will result in a runtime error. We have strengthened our `RouteObject`/`RouteProps` types to surface the error in TypeScript. ([#&#8203;9366](https://github.com/remix-run/react-router/pull/9366)) - Updated dependencies: - `@remix-run/router@1.0.2` ### [`v6.4.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;641) [Compare Source](https://github.com/remix-run/react-router/compare/react-router@6.4.0...react-router@6.4.1) ##### Patch Changes - Preserve state from `initialEntries` ([#&#8203;9288](https://github.com/remix-run/react-router/pull/9288)) - Updated dependencies: - `@remix-run/router@1.0.1` ### [`v6.4.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#&#8203;640) [Compare Source](https://github.com/remix-run/react-router/compare/v6.3.0...react-router@6.4.0) Whoa this is a big one! `6.4.0` brings all the data loading and mutation APIs over from Remix. Here's a quick high level overview, but it's recommended you go check out the [docs](https://reactrouter.com), especially the [feature overview](https://reactrouter.com/start/overview) and the [tutorial](https://reactrouter.com/start/tutorial). **New APIs** - Create your router with `createMemoryRouter` - Render your router with `<RouterProvider>` - Load data with a Route `loader` and mutate with a Route `action` - Handle errors with Route `errorElement` - Defer non-critical data with `defer` and `Await` **Bug Fixes** - Path resolution is now trailing slash agnostic ([#&#8203;8861](https://github.com/remix-run/react-router/issues/8861)) - `useLocation` returns the scoped location inside a `<Routes location>` component ([#&#8203;9094](https://github.com/remix-run/react-router/issues/9094)) **Updated Dependencies** - `@remix-run/router@1.0.0` ### [`v6.3.0`](https://github.com/remix-run/react-router/releases/tag/v6.3.0): react-router@v6.3.0 [Compare Source](https://github.com/remix-run/react-router/compare/v6.2.2...v6.3.0) ##### What's Changed - Added the v5 to v6 backwards compatibility package 💜 (https://github.com/remix-run/react-router/pull/8752). The official guide can be found [in this discussion](https://github.com/remix-run/react-router/discussions/8753) ##### New Contributors - [@&#8203;mfijas](https://github.com/mfijas) made their first contribution in https://github.com/remix-run/react-router/pull/8717 - [@&#8203;ThornWu](https://github.com/ThornWu) made their first contribution in https://github.com/remix-run/react-router/pull/8718 - [@&#8203;janpaepke](https://github.com/janpaepke) made their first contribution in https://github.com/remix-run/react-router/pull/8651 - [@&#8203;rtmann](https://github.com/rtmann) made their first contribution in https://github.com/remix-run/react-router/pull/8725 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.2.2...v6.3.0 ### [`v6.2.2`](https://github.com/remix-run/react-router/releases/tag/v6.2.2) [Compare Source](https://github.com/remix-run/react-router/compare/v6.2.1...v6.2.2) ##### What's Changed ##### 🐛 Bug Fixes - Fixed nested splat routes that begin with special URL-safe characters ([#&#8203;8563](https://github.com/remix-run/react-router/issues/8563)) - Fixed a bug where index routes were missing route context in some cases ([#&#8203;8497](https://github.com/remix-run/react-router/issues/8497)) ##### New Contributors - [@&#8203;chasinhues](https://github.com/chasinhues) made their first contribution in https://github.com/remix-run/react-router/pull/8514 - [@&#8203;underager](https://github.com/underager) made their first contribution in https://github.com/remix-run/react-router/pull/8531 - [@&#8203;kantuni](https://github.com/kantuni) made their first contribution in https://github.com/remix-run/react-router/pull/8537 - [@&#8203;ArjaanBuijk](https://github.com/ArjaanBuijk) made their first contribution in https://github.com/remix-run/react-router/pull/8536 - [@&#8203;jmargeta](https://github.com/jmargeta) made their first contribution in https://github.com/remix-run/react-router/pull/8548 - [@&#8203;koojaa](https://github.com/koojaa) made their first contribution in https://github.com/remix-run/react-router/pull/8542 - [@&#8203;chrisngobanh](https://github.com/chrisngobanh) made their first contribution in https://github.com/remix-run/react-router/pull/8576 - [@&#8203;ChristopherChudzicki](https://github.com/ChristopherChudzicki) made their first contribution in https://github.com/remix-run/react-router/pull/8582 - [@&#8203;awreese](https://github.com/awreese) made their first contribution in https://github.com/remix-run/react-router/pull/8596 - [@&#8203;bhbs](https://github.com/bhbs) made their first contribution in https://github.com/remix-run/react-router/pull/8601 - [@&#8203;LukerSpringtree](https://github.com/LukerSpringtree) made their first contribution in https://github.com/remix-run/react-router/pull/8619 - [@&#8203;hsbtr](https://github.com/hsbtr) made their first contribution in https://github.com/remix-run/react-router/pull/8476 - [@&#8203;abhi-kr-2100](https://github.com/abhi-kr-2100) made their first contribution in https://github.com/remix-run/react-router/pull/8658 - [@&#8203;cvbuelow](https://github.com/cvbuelow) made their first contribution in https://github.com/remix-run/react-router/pull/8663 - [@&#8203;hyesungoh](https://github.com/hyesungoh) made their first contribution in https://github.com/remix-run/react-router/pull/8666 - [@&#8203;BrianT1414](https://github.com/BrianT1414) made their first contribution in https://github.com/remix-run/react-router/pull/8667 - [@&#8203;IbraRouisDev](https://github.com/IbraRouisDev) made their first contribution in https://github.com/remix-run/react-router/pull/8683 - [@&#8203;shihanng](https://github.com/shihanng) made their first contribution in https://github.com/remix-run/react-router/pull/8689 - [@&#8203;latin-1](https://github.com/latin-1) made their first contribution in https://github.com/remix-run/react-router/pull/8529 - [@&#8203;Isammoc](https://github.com/Isammoc) made their first contribution in https://github.com/remix-run/react-router/pull/8533 - [@&#8203;KutnerUri](https://github.com/KutnerUri) made their first contribution in https://github.com/remix-run/react-router/pull/8278 - [@&#8203;shamsup](https://github.com/shamsup) made their first contribution in https://github.com/remix-run/react-router/pull/8563 - [@&#8203;brophdawg11](https://github.com/brophdawg11) made their first contribution in https://github.com/remix-run/react-router/pull/8691 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.2.1...v6.2.2 ### [`v6.2.1`](https://github.com/remix-run/react-router/releases/tag/v6.2.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.2.0...v6.2.1) This release updates the internal `history` dependency to `5.2.0`. **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.2.0...v6.2.1 ### [`v6.2.0`](https://github.com/remix-run/react-router/releases/tag/v6.2.0) [Compare Source](https://github.com/remix-run/react-router/compare/v6.1.1...v6.2.0) #### 🐛 Bug fixes - Fixed the `RouteProps` `element` type, which should be a `ReactNode` ([#&#8203;8473](https://github.com/remix-run/react-router/issues/8473)) - Fixed a bug with `useOutlet` for top-level routes ([#&#8203;8483](https://github.com/remix-run/react-router/issues/8483)) #### ✨ Features - We now use statically analyzable CJS exports. This enables named imports in Node ESM scripts ([See the commit](https://github.com/remix-run/react-router/commit/29c7fc8b5f853b0b06ecd0f5682a9bbe6eca0715)). #### New Contributors - [@&#8203;thisiskartik](https://github.com/thisiskartik) made their first contribution in https://github.com/remix-run/react-router/pull/8487 - [@&#8203;vijaypushkin](https://github.com/vijaypushkin) made their first contribution in https://github.com/remix-run/react-router/pull/8491 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.1.1...v6.2.0 ### [`v6.1.1`](https://github.com/remix-run/react-router/releases/tag/v6.1.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.1.0...v6.1.1) In v6.1.0 we inadvertently shipped a new, undocumented API that will likely introduce bugs ([#&#8203;7586](https://github.com/remix-run/react-router/issues/7586)). We have flagged `HistoryRouter` as `unstable_HistoryRouter`, as this API will likely need to change before a new major release. **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.1.0...v6.1.1 ### [`v6.1.0`](https://github.com/remix-run/react-router/releases/tag/v6.1.0) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.2...v6.1.0) #### 🐛 Bug fixes - Fixed a bug that broke support for base64 encoded IDs on nested routes ([#&#8203;8291](https://github.com/remix-run/react-router/issues/8291)) #### ✨ Features - `<Outlet>` can now receive a `context` prop. This value is passed to child routes and is accessible via the new `useOutletContext` hook. See [the API docs](https://reactrouter.com/docs/en/v6/api#useoutletcontext) for details. ([#&#8203;8461](https://github.com/remix-run/react-router/issues/8461)) - `<NavLink>` can now receive a child function for access to its props. ([#&#8203;8164](https://github.com/remix-run/react-router/issues/8164)) #### 💅 Enhancements - Improved TypeScript signature for `useMatch` and `matchPath`. For example, when you call `useMatch("foo/:bar/:baz")`, the path is parsed and the return type will be `PathMatch<"bar" | "baz">`. ([#&#8203;8030](https://github.com/remix-run/react-router/issues/8030)) - A few error message improvements ([#&#8203;8202](https://github.com/remix-run/react-router/issues/8202)) #### New Contributors - [@&#8203;rwieruch](https://github.com/rwieruch) made their first contribution in https://github.com/remix-run/react-router/pull/8244 - [@&#8203;codeiotic](https://github.com/codeiotic) made their first contribution in https://github.com/remix-run/react-router/pull/8247 - [@&#8203;Sannnao](https://github.com/Sannnao) made their first contribution in https://github.com/remix-run/react-router/pull/8263 - [@&#8203;mattmazzola](https://github.com/mattmazzola) made their first contribution in https://github.com/remix-run/react-router/pull/8255 - [@&#8203;ngokevin](https://github.com/ngokevin) made their first contribution in https://github.com/remix-run/react-router/pull/8267 - [@&#8203;TimisRobert](https://github.com/TimisRobert) made their first contribution in https://github.com/remix-run/react-router/pull/8269 - [@&#8203;mikeldking](https://github.com/mikeldking) made their first contribution in https://github.com/remix-run/react-router/pull/8279 - [@&#8203;fishmandev](https://github.com/fishmandev) made their first contribution in https://github.com/remix-run/react-router/pull/8289 - [@&#8203;rjerue](https://github.com/rjerue) made their first contribution in https://github.com/remix-run/react-router/pull/8304 - [@&#8203;rockingskier](https://github.com/rockingskier) made their first contribution in https://github.com/remix-run/react-router/pull/8314 - [@&#8203;arinthros](https://github.com/arinthros) made their first contribution in https://github.com/remix-run/react-router/pull/8337 - [@&#8203;noisypigeon](https://github.com/noisypigeon) made their first contribution in https://github.com/remix-run/react-router/pull/8361 - [@&#8203;elylucas](https://github.com/elylucas) made their first contribution in https://github.com/remix-run/react-router/pull/8368 - [@&#8203;paulsmithkc](https://github.com/paulsmithkc) made their first contribution in https://github.com/remix-run/react-router/pull/8357 - [@&#8203;sanketshah19](https://github.com/sanketshah19) made their first contribution in https://github.com/remix-run/react-router/pull/8372 - [@&#8203;JakubDrozd](https://github.com/JakubDrozd) made their first contribution in https://github.com/remix-run/react-router/pull/8402 - [@&#8203;markivancho](https://github.com/markivancho) made their first contribution in https://github.com/remix-run/react-router/pull/8414 - [@&#8203;turansky](https://github.com/turansky) made their first contribution in https://github.com/remix-run/react-router/pull/8420 - [@&#8203;shivamsinghchahar](https://github.com/shivamsinghchahar) made their first contribution in https://github.com/remix-run/react-router/pull/8423 - [@&#8203;petersendidit](https://github.com/petersendidit) made their first contribution in https://github.com/remix-run/react-router/pull/8436 - [@&#8203;Ajayff4](https://github.com/Ajayff4) made their first contribution in https://github.com/remix-run/react-router/pull/8373 - [@&#8203;RobHannay](https://github.com/RobHannay) made their first contribution in https://github.com/remix-run/react-router/pull/8455 - [@&#8203;kddnewton](https://github.com/kddnewton) made their first contribution in https://github.com/remix-run/react-router/pull/8030 - [@&#8203;brockross](https://github.com/brockross) made their first contribution in https://github.com/remix-run/react-router/pull/8462 - [@&#8203;sergiodxa](https://github.com/sergiodxa) made their first contribution in https://github.com/remix-run/react-router/pull/8164 - [@&#8203;baozouai](https://github.com/baozouai) made their first contribution in https://github.com/remix-run/react-router/pull/8171 - [@&#8203;liuhanqu](https://github.com/liuhanqu) made their first contribution in https://github.com/remix-run/react-router/pull/8374 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.0.1...v6.1.0 ### [`v6.0.2`](https://github.com/remix-run/react-router/releases/tag/v6.0.2) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.1...v6.0.2) #### ✨ Features - Added the `reloadDocument` prop to `<Link>`. This allows `<Link>` to function like a normal anchor tag by reloading the document after navigation while maintaining the relative `to` resolution. #### 🗒️ Docs - Fixed several issues in docblocks and the docs themselves. See the [full changelog](https://github.com/remix-run/react-router/compare/v6.0.1...v6.0.2) for the deets! #### 🤝 New Contributors - [@&#8203;rwieruch](https://github.com/rwieruch) made their first contribution in https://github.com/remix-run/react-router/pull/8244 - [@&#8203;ProProgrammer2504](https://github.com/ProProgrammer2504) made their first contribution in https://github.com/remix-run/react-router/pull/8247 - [@&#8203;Sannnao](https://github.com/Sannnao) made their first contribution in https://github.com/remix-run/react-router/pull/8263 - [@&#8203;mattmazzola](https://github.com/mattmazzola) made their first contribution in https://github.com/remix-run/react-router/pull/8255 - [@&#8203;ngokevin](https://github.com/ngokevin) made their first contribution in https://github.com/remix-run/react-router/pull/8267 - [@&#8203;TimisRobert](https://github.com/TimisRobert) made their first contribution in https://github.com/remix-run/react-router/pull/8269 - [@&#8203;mikeldking](https://github.com/mikeldking) made their first contribution in https://github.com/remix-run/react-router/pull/8279 - [@&#8203;fishmandev](https://github.com/fishmandev) made their first contribution in https://github.com/remix-run/react-router/pull/8289 ##### Full Changelog ### [`v6.0.1`](https://github.com/remix-run/react-router/releases/tag/v6.0.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0...v6.0.1) #### 🐛 Bug Fixes - Add a default `<StaticRouter location>` value ([#&#8203;8243](https://github.com/remix-run/react-router/issues/8243)) - Add invariant for using `<Route>` inside `<Routes>` to help people make the change ([#&#8203;8238](https://github.com/remix-run/react-router/issues/8238)) ### [`v6.0.0`](https://github.com/remix-run/react-router/releases/tag/v6.0.0) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.8...v6.0.0) React Router v6 is here! Please go read [our blog post for more information on all the great stuff in v6](https://remix.run/blog/react-router-v6) including [notes about how to upgrade from React Router v5](https://remix.run/blog/react-router-v6#upgrading-to-react-router-v6) and Reach Router. ### [`v6.0.0-beta.8`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.8) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.7...v6.0.0-beta.8) Remember last week when we said > We anticipate this will be the last beta release before v6 stable next week. Yeah, about that … 😅 We found and squashed a few high-priority bugs that needed to be addressed first. But it's coming very soon, we promise! In the mean time, here's what you'll get from our eight-est and greatest beta release: #### 🐛 Bug Fixes - We fixed a few bugs in `useHref` that resulted in the incorrect resolved value in cases where a `basename` is used on the `<Router />` component (See [#&#8203;8133](https://github.com/remix-run/react-router/issues/8133) and [#&#8203;8142](https://github.com/remix-run/react-router/issues/8142) for details). - We also fixed a bug in our path ranking algorithm so that splat routes (routes with a `*` path value) are now correctly ranked ahead of layout routes. #### 🗒️ Docs We've added lots of goodies to our `docs` and `examples`, and there's a lot more yet to come. Take a look and see if you find something that makes your work a little easier! We think the [lazy loading](https://github.com/remix-run/react-router/tree/dev/examples/lazy-loading) and [custom query parsing](https://github.com/remix-run/react-router/tree/dev/examples/custom-query-parsing) examples are particularly cool! 🤓 ### [`v6.0.0-beta.7`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.7) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.6...v6.0.0-beta.7) In this release we made a small but significant change to how `<Link to="..">` works. This is going to help out a lot if you were trying to use links in a `*` route. We have also backed out our blocking/prompt APIs for the stable v6 release. We will revisit this post 6.0 when we have a little more time to get it right. #### ✨ Features The major change in this release could also be classified as a bugfix or a breaking change, depending on how you look at it. We essentialy altered the way `<Link to="..">` works. See [#&#8203;8086](https://github.com/remix-run/react-router/issues/8086) for the motivation behind this change. You'll probably want to reread [the section in the v5 => v6 migration guide about `<Link to>` values](https://github.com/remix-run/react-router/blob/main/docs/guides/migrating-5-to-6.md#note-on-link-to-values) (it has been updated), but it basically boils down to this: **any leading `..` segment in a `<Link to>` value traverses "up" one route and builds upon that route's path instead of just removing one URL segment**. This feature really completes the story of relative routes and links. We could consider this a bugfix, since this is how it was always intended to work in the first place. Without it, you'd have a difficult time linking predictably in `*` routes because your `<a href>` would be different depending on the number of segments in the current URL. The reason this could also be considered a breaking change is that `..` now works slightly differently in `<Link to>` than it would in `<a href>`. When you have `<a href="..">` it operates on the URL pathname, removing one segment of the current URL. However, since many routes really only match a single segment of the URL, there is often no difference between `<Link to="..">` and `<a href="..">`. #### 💔 Breaking Changes - We removed `useBlocker()`, `usePrompt()`, and `<Prompt>` for now. We will revisit these post 6.0 when we have more time to get it right. But we don't want it to *block* (see what I did there) the release of all the other awesome stuff we've got in v6. #### 🛠 Roadmap We anticipate this will be the last beta release before v6 stable next week. Please give it a shot and let us know how it goes! #### 👍 Upgrading If you're thinking about upgrading to v6, I published a few notes this past week that may help you: - [This note talks about removing `<Redirect>` elements from any `<Switch>`es you may have in your v5 app](https://gist.github.com/mjackson/b5748add2795ce7448a366ae8f8ae3bb) and how you can get better SEO in the process if you're currently relying on client-side redirects. - [This note talks about how to refactor your code to avoid "wrapping" `<Route>` elements](https://gist.github.com/mjackson/d54b40a094277b7afdd6b81f51a0393f), which won't work in v6. Both of those posts contain steps you can take **today in your v5 app** without upgrading to v6. We are also developing a backwards compat lib that should help some of you upgrade from v5 to v6. We'll post more about this when it's ready. #### 💻 Installing Development for v6 has switched from `dev` [to the `main` branch](https://github.com/remix-run/react-router/tree/main). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.6`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.6) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.5...v6.0.0-beta.6) No big enhancements in this release, just squashing bugs and writing lots of tests! Also, we are hard at work on cranking out examples for v6. See the end of this post for an update on our roadmap between here and v6 stable. #### 🧰 Examples We have begun creating some examples for v6 that we hope will help developers make effective use of all the new features we have. So far, we have examples for the following: - [Basic Example](https://github.com/remix-run/react-router/tree/dev/examples/basic) – A basic client-side app for v6 showing how to use nested routes, layouts, links, and the new `<Outlet>` API - [Auth Example](https://github.com/remix-run/react-router/tree/dev/examples/auth) – Demonstrates an authentication flow including using the new `useNavigate()` hook, the `<Navigate>` element, and `location.state` - [Search Params Example](https://github.com/remix-run/react-router/tree/dev/examples/search-params) – Demonstrates how to build a simple search form that uses the new `useSearchParams()` hook - [SSR Example](https://github.com/remix-run/react-router/tree/dev/examples/ssr) – A server-rendered app that uses `<StaticRouter>` on the server and uses a `<BrowserRouter>` with `ReactDOM.hydrate()` on the client Each example includes a button in the README that allows you to instantly launch a running instance on StackBlitz that you can play with. We hope you enjoy exploring! #### 🐛 Bugfixes - Make `<NavLink>` match only whole URL segments instead of pieces. This means that `<NavLink to="/home/users">` will still be active at `/home/users`, but not at `/home/users2`. See [#&#8203;7523](https://github.com/remix-run/react-router/issues/7523) - Makes "layout routes" (routes with no `path`) never match unless one of their children do. See [#&#8203;8085](https://github.com/remix-run/react-router/issues/8085) - Fixes a route matching regression with splat routes that was introduced in beta.5. See [#&#8203;8072](https://github.com/remix-run/react-router/issues/8072) and [#&#8203;8109](https://github.com/remix-run/react-router/issues/8109) - Fixes matching a nested splat route. See [`af7d038`](https://github.com/remix-run/react-router/commit/af7d038e) - Provide all parent route params to descendant `<Routes>`. This reverses a decision that we made in beta.5 to remove them. See [#&#8203;8073](https://github.com/remix-run/react-router/issues/8073) #### 💔 Breaking Changes - Splats in route paths (`*`) match only after a `/` in the URL. This means that `<Route path="files*">` will always match as if it were `<Route path="files/*">`. The router will issue a warning if your route path ends with `*` but not `/*` #### 🛠 Roadmap We are very close to a stable release! The last big code changes we need to make are: - Fixing "linking up". Currently a `<Link to="..">` operates on the URL pathname. However, this makes it difficult to link to the parent route when you're in a splat route. See [#&#8203;8086](https://github.com/remix-run/react-router/issues/8086). This will be a breaking change. - We are going to remove `useBlocker()` and `<Prompt>` in our initial v6 release, with plans to revisit them and possibly add them back at some point in the future. I still need to write up something here that explains our rationale. This will also be a breaking change. - We are going to add some animation primitives (see https://github.com/remix-run/react-router/discussions/8008). The `<Routes location>` prop will be in v6, but it isn't ideal for animation. #### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.5`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.5) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.4...v6.0.0-beta.5) This week's release adds some much-needed polish to a few niche features of the router: splat routes (a route that uses a `*` path) and basenames. It also adds a `renderMatches` API that completes the story for those of you who may have been using `react-router-config` in v4 and v5. #### 🐛 Bugfixes - A `*` in a child route path matches *after* a slash following its parent route path. This fixes some situations where the `*` was overly greedy (see [#&#8203;7972](https://github.com/remix-run/react-router/issues/7972)) - Resolution of `<Link to=".">` and `useResolvedPath(".")` values are fixed in splat routes. Previously these resolved relative to the parent route's path. They now resolve relative to the path of the route that rendered them. #### ✨ Enhancements This release makes it easier to work with apps that have multiple entry points. Using the `<Router basename>` prop allows React Router to be easily deployed on only a portion of a larger site by using a portion of the URL pathname (the "basename") to transparently prefix all route paths and link navigations. For example, you can deploy one React Router app at the `/inbox` URL prefix, and another one at the `/admin` prefix. These base URLs represent two different entry points into your app, each with its own bundles. The rest of your site, including the root / URL could be rendered by something other than React Router, for example by your server framework of choice. In the bundle for each entry point, simply initialize React Router with the basename of that entry point. ```tsx <Router basename="/inbox"> // ... </Router> ``` Then define your routes and link paths without using the `/inbox` URL prefix in any of them. The entire app will run relative to that prefix. Another improvement in this release is the addition of the `renderMatches` API, which is the complement of `matchRoutes`. These APIs are both very low-level and should not normally be needed. But they are sometimes nice to use if you are doing your own data loading using the array of `matches` that you get back from `matchRoutes`. `matchRoutes` and `renderMatches` are the equivalent of the `react-router-config` package we shipped in v4 and v5, just built directly into the router instead of in a separate package. #### 💔 Breaking Changes - `<Routes basename>` has moved to `<Router basename>`. This prop is also available on all router variants (`<BrowserRouter>`, `<HashRouter>`, etc.). - `useLocation().pathname` no longer includes the basename, if present. - The `basename` argument was removed from `useRoutes`. This reverts the signature to `useRoutes(routes, location)`, same as it was previous to beta.4. - Descendant `<Routes>` do not get the params from their parents. This helps a set of `<Routes>` to be more portable by decoupling it from the params of its parents and makes it easier to know which params will be returned from `useParams()`. If you were relying on this behavior previously, you'll need to pass along the params manually to the elements rendered by the descendant `<Routes>`. See [this comment](https://github.com/remix-run/react-router/issues/8073#issuecomment-929687218) for an example of how this is to be done and for a potential workaround if you really need the old behavior. - `match.pathname` in a splat route now includes the portion of the pathname matched by the `*`. This makes the `*` param behave much more like other dynamic `:id`-style params. - Resolution of relative `<Link>`s in splat routes is changed now because the entire pathname that was matched by that route is now different (see previous bullet). Instead of resolving relative to the portion of the pathname before the `*`, paths resolve relative to the full pathname that was matched by the route. #### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.4`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.4) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.3...v6.0.0-beta.4) Last week we released a lot of nice little bug features, but we did get a little carried away and let a little bug slip through with relative path resolution. Our bad! That nasty lil' guy is squashed in this week's beta. 🐛 And there's more! Let's dive in… #### 🐛 Bugfixes - Path resolution for nested relative routes was broken in the last release and should now be fixed. Nested routes construct their pathname based on the location of their parent, *not* the current location. This is explained in detail under [Relative Routes and Links in our advanced guides](docs/advanced-guides/migrating-5-to-6.md#relative-routes-and-links), and the issue itself in [#&#8203;8004](https://github.com/remix-run/react-router/issues/8004) #### ✨ Enhancements - We made some enhancements with the `Params` type which is now generic, so you can add your own types if you know what to expect from functions that return query parameters. ([#&#8203;8019](https://github.com/remix-run/react-router/issues/8019)) ```tsx // before let { valid, invalid } = useParams(); // No problems here! let match = useMatch("profile/:userId"); let userId = match?.params.user; // wrong param, but TS doesn't know that! // after: let { valid, invalid } = useParams<"valid" | "key">(); // Property 'invalid' does not exist on type 'Params<"valid" | "key">' let match = useMatch<"userId">("profile/:userId"); let userId = match?.params.user; // Property 'user' does not exist on type 'Params<"userId">' ``` - Absolute nested path support There was quite a bit of discussion in [#&#8203;7335](https://github.com/remix-run/react-router/issues/7335) from people who are using constants to define their route paths. In this style, paths are often written as absolute paths from the root `/` URL. These constants are then able to be used both in `<Route path>` definitions as well as `<Link to>` values. It usually looks something like this: ```tsx const USERS_PATH = "/users"; const USERS_INDEX_PATH = `${USERS_PATH}/`; const USER_PROFILE_PATH = `${USERS_PATH}/:id`; function UsersRoutes() { return ( <Routes> <Route path={USERS_PATH} element={<UsersLayout />}> <Route path={USERS_INDEX_PATH} element={<UsersIndex />} /> <Route path={USER_PROFILE_PATH} element={<UserProfile />} /> </Route> </Routes> ); } ``` This style of use is now fully supported in v6. This is great for people who write their apps like this, but **it technically could cause some breakage** if you were using absolute paths (that start with `/`) in nested routes in previous betas. To fix this, simply **remove the `/` from the beginning of any route paths that are meant to be relative**. React Router will throw an error if you are using absolute paths that don't match their parent route paths. Hopefully this should help you find them if you are upgrading. If you were using `<Route path="/">` to indicate an index route, you can now use the new `<Route index>` prop to accomplish the same thing. The `index` prop makes it easy to scan a route config to find the index route. It also provides a guarantee that nobody will ever add children to that route. Here's the same route config as the one above, but rewritten with relative paths and the `index` prop: ```tsx function UsersRoutes() { return ( <Routes> <Route path="users" element={<UsersLayout />}> <Route index element={<UsersIndex />} /> <Route path=":id" element={<UserProfile />} /> </Route> </Routes> ); } ``` A lot of our work on React Router is about doing the **least surprising** thing for our users. Allowing absolute paths in nested routes gets us a little closer to that goal! #### 💔 Breaking Changes - Removed the ability for nested route paths to begin with a `/` and not contain the complete path of their parent routes. This was necessary in order to introduce support for absolute paths in nested routes, described in detail above - Removed the `createRoutesFromArray` utility function. You can now pass your routes directly to `useRoutes` or `matchRoutes` without passing it through `createRoutesFromArray` first - Removed the `PartialRouteObject` type. If you were importing and using this type before, use `RouteObject` instead, which has been updated to make all properties optional - The `useRoutes` API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object: ```tsx // Before useRoutes([...routes], basename); // After useRoutes([...routes], { basename }); ``` - The `matchPath` function now returns `match.pattern` instead of `match.path`, which is a little more descriptive about what it actually is #### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.3`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.3) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.2...v6.0.0-beta.3) Loads of goodies for you this week, as well as a few breaking changes for all of you eager beavers who are brave enough to use beta software in production! 🦫 (seriously, thank you all for helping us tighten up our APIs and fix nasty bugs) #### 💔 Breaking Changes! - `NavLink` no longer supports the `activeClassName` or `activeStyle` props. Instead, we provide a more powerful API that allows you to pass functions to either the `className` or `style` props to conditionally apply values based on the link's `active` state. While a bit more verbose in some cases, this offers a nicer experience for folks who use utility class-based CSS. ([#&#8203;7194](https://github.com/remix-run/react-router/issues/7194)) ```tsx // Before <NavLink className="link" activeClassName="active-link" /> <NavLink style={{ color: "blue" }} activeStyle={{ color: "green" }} /> // After <NavLink className={({ isActive }) => `link ${ isActive ? "active-link" : // Couldn't do this before! "inactive-link" }` } /> <NavLink style={({ isActive }) => ({ color: isActive ? "green" : "blue" })} /> ``` > **Note:** You can always abstract over this feature in a custom `NavLink` if you prefer the old v5 API. - The `useRoutes` API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object: ```tsx // Before useRoutes([...routes], basename); // After useRoutes([...routes], { basename }); ``` #### 🐛 Bugfixes - The `basename` prop on `Routes` is treated as case-insensitive ([#&#8203;7997](https://github.com/remix-run/react-router/issues/7997)) - `useNavigate` previously used the incorrect `pathname` when called from parent routes when the URL matches one of its children. This fix also applies to `useSearchParams` ([#&#8203;7880](https://github.com/remix-run/react-router/issues/7880)) #### ✨ Enhancements - `Routes` and `useRoutes` now allow you to override the `location`, which may be useful when building some modal interfaces and route transition animations. We are working hard to update our docs to include examples for advanced patterns where this might be useful, but in the mean time this also brings `Routes` closer to feature parity with v5's `Switch` via the `location` prop. ([#&#8203;7117](https://github.com/remix-run/react-router/issues/7117)) - Provided new hooks `useClickHandler` and `usePressHandler` to make customizing `Links` a bit easier. ([#&#8203;7998](https://github.com/remix-run/react-router/issues/7998)) - **Please note:** with great power comes great responsibility. If you create a custom `Link`, be sure to render an actual HTML anchor element, otherwise your app will likely be inaccessible without a significant amount of additional work which, I assure you, you don't want to do! #### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` #### 🙏 Credits Thanks to [@&#8203;andrelandgraf](https://github.com/andrelandgraf), [@&#8203;dhulme](https://github.com/dhulme), [@&#8203;fgatti675](https://github.com/fgatti675), [@&#8203;hugmanrique](https://github.com/hugmanrique), [@&#8203;MeiKatz](https://github.com/MeiKatz), [@&#8203;chaance](https://github.com/chaance) and [@&#8203;mjackson](https://github.com/mjackson) for your contributions! ### [`v6.0.0-beta.2`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.2) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.1...v6.0.0-beta.2) #### 🐛 Bugfixes - Fixed a bug that [broke paths in nested routes](https://github.com/remix-run/react-router/issues/7948) - Adds missing `displayName` back to `<Link />` and `<NavLink />` components #### ✨ Enhancements - The `navigate` function now prepends hash and search strings by default: ```js navigate({ search: "?foo=1&bar=2" }); // this works as expected! navigate({ search: "foo=1&bar=2" }); // this also works! ``` - `useParams` now returns [parameters from nested `<Route />`s when called in a parent `<Route />`](https://github.com/remix-run/react-router/issues/7960) #### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` #### 🙏 Credits Thanks to [@&#8203;liho98](https://github.com/liho98), [@&#8203;wojtekmaj](https://github.com/wojtekmaj), [@&#8203;cravend](https://github.com/cravend), [@&#8203;chaance](https://github.com/chaance) and [@&#8203;mjackson](https://github.com/mjackson) for your contributions! Enjoy! ### [`v6.0.0-beta.1`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.0...v6.0.0-beta.1) We're on the road to a stable v6 release! There are no new features in this release since `beta.0`, but a handful of squashed bugs, perf enhancements, and DX improvements for TypeScript users. #### 🐛 Bugfixes - Fixed a few bugs with pathname resolution. `+` characters no longer get decoded into spaces, and that little [`*` is just a little less greedy](https://github.com/remix-run/react-router/issues/7529) (e.g., `app/*` no longer matches `apples/*`). - `Link` and `navigate` should properly [respect the `basename` when using absolute paths](https://github.com/remix-run/react-router/issues/7216). #### ✨ Enhancements - Internally we are separating `navigator` into a separate context object, meaning your components that call `useNavigate` will probably render a little less often. Wowza, much perf! - `react-router-dom` and `react-router-native` now re-exports all types exported from `react-router` #### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` #### 🙏 Credits Thanks to [@&#8203;brookslybrand](https://github.com/brookslybrand), [@&#8203;bogdansoare](https://github.com/bogdansoare), [@&#8203;chaance](https://github.com/chaance) and [@&#8203;mjackson](https://github.com/mjackson) for your contributions! Enjoy! </details> <details> <summary>remix-run/react-router (react-router-dom)</summary> ### [`v6.22.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6223) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.22.2...react-router-dom@6.22.3) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.15.3` - `react-router@6.22.3` ### [`v6.22.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6222) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.22.1...react-router-dom@6.22.2) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.15.2` - `react-router@6.22.2` ### [`v6.22.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6221) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.22.0...react-router-dom@6.22.1) ##### Patch Changes - Updated dependencies: - `react-router@6.22.1` - `@remix-run/router@1.15.1` ### [`v6.22.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6220) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.21.3...react-router-dom@6.22.0) ##### Minor Changes - Include a `window__reactRouterVersion` tag for CWV Report detection ([#&#8203;11222](https://github.com/remix-run/react-router/pull/11222)) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.15.0` - `react-router@6.22.0` ### [`v6.21.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6213) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.21.2...react-router-dom@6.21.3) ##### Patch Changes - Fix `NavLink` `isPending` when a `basename` is used ([#&#8203;11195](https://github.com/remix-run/react-router/pull/11195)) - Remove leftover `unstable_` prefix from `Blocker`/`BlockerFunction` types ([#&#8203;11187](https://github.com/remix-run/react-router/pull/11187)) - Updated dependencies: - `react-router@6.21.3` ### [`v6.21.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6212) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.21.1...react-router-dom@6.21.2) ##### Patch Changes - Leverage `useId` for internal fetcher keys when available ([#&#8203;11166](https://github.com/remix-run/react-router/pull/11166)) - Updated dependencies: - `@remix-run/router@1.14.2` - `react-router@6.21.2` ### [`v6.21.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6211) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.21.0...react-router-dom@6.21.1) ##### Patch Changes - Updated dependencies: - `react-router@6.21.1` - `@remix-run/router@1.14.1` ### [`v6.21.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6210) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.20.1...react-router-dom@6.21.0) ##### Minor Changes - Add a new `future.v7_relativeSplatPath` flag to implement a breaking bug fix to relative routing when inside a splat route. ([#&#8203;11087](https://github.com/remix-run/react-router/pull/11087)) This fix was originally added in [#&#8203;10983](https://github.com/remix-run/react-router/issues/10983) and was later reverted in [#&#8203;11078](https://github.com/remix-run/react-router/pull/11078) because it was determined that a large number of existing applications were relying on the buggy behavior (see [#&#8203;11052](https://github.com/remix-run/react-router/issues/11052)) **The Bug** The buggy behavior is that without this flag, the default behavior when resolving relative paths is to *ignore* any splat (`*`) portion of the current route path. **The Background** This decision was originally made thinking that it would make the concept of nested different sections of your apps in `<Routes>` easier if relative routing would *replace* the current splat: ```jsx <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="dashboard/*" element={<Dashboard />} /> </Routes> </BrowserRouter> ``` Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects` will match the `Dashboard` route. The dashboard component itself can then render nested `<Routes>`: ```jsx function Dashboard() { return ( <div> <h2>Dashboard</h2> <nav> <Link to="/">Dashboard Home</Link> <Link to="team">Team</Link> <Link to="projects">Projects</Link> </nav> <Routes> <Route path="/" element={<DashboardHome />} /> <Route path="team" element={<DashboardTeam />} /> <Route path="projects" element={<DashboardProjects />} /> </Routes> </div> ); } ``` Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the `Dashboard` as its own independent app, or embed it into your large app without making any changes to it. **The Problem** The problem is that this concept of ignoring part of a path breaks a lot of other assumptions in React Router - namely that `"."` always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using `"."`: ```jsx // If we are on URL /dashboard/team, and we want to link to /dashboard/team: function DashboardTeam() { // ❌ This is broken and results in <a href="/dashboard"> return <Link to=".">A broken link to the Current URL</Link>; // ✅ This is fixed but super unintuitive since we're already at /dashboard/team! return <Link to="./team">A broken link to the Current URL</Link>; } ``` We've also introduced an issue that we can no longer move our `DashboardTeam` component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as `/dashboard/:widget`. Now, our `"."` links will, properly point to ourself *inclusive of the dynamic param value* so behavior will break from it's corresponding usage in a `/dashboard/*` route. Even worse, consider a nested splat route configuration: ```jsx <BrowserRouter> <Routes> <Route path="dashboard"> <Route path="*" element={<Dashboard />} /> </Route> </Routes> </BrowserRouter> ``` Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard` component go to the same place! That is definitely not correct! Another common issue arose in Data Routers (and Remix) where any `<Form>` should post to it's own route `action` if you the user doesn't specify a form action: ```jsx let router = createBrowserRouter({ path: "/dashboard", children: [ { path: "*", action: dashboardAction, Component() { // ❌ This form is broken! It throws a 405 error when it submits because // it tries to submit to /dashboard (without the splat value) and the parent // `/dashboard` route doesn't have an action return <Form method="post">...</Form>; }, }, ], }); ``` This is just a compounded issue from the above because the default location for a `Form` to submit to is itself (`"."`) - and if we ignore the splat portion, that now resolves to the parent route. **The Solution** If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage `../` for any links to "sibling" pages: ```jsx <BrowserRouter> <Routes> <Route path="dashboard"> <Route index path="*" element={<Dashboard />} /> </Route> </Routes> </BrowserRouter> function Dashboard() { return ( <div> <h2>Dashboard</h2> <nav> <Link to="..">Dashboard Home</Link> <Link to="../team">Team</Link> <Link to="../projects">Projects</Link> </nav> <Routes> <Route path="/" element={<DashboardHome />} /> <Route path="team" element={<DashboardTeam />} /> <Route path="projects" element={<DashboardProjects />} /> </Router> </div> ); } ``` This way, `.` means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and `..` always means "my parents pathname". ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.14.0` - `react-router@6.21.0` ### [`v6.20.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6201) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.20.0...react-router-dom@6.20.1) ##### Patch Changes - Revert the `useResolvedPath` fix for splat routes due to a large number of applications that were relying on the buggy behavior (see [#&#8203;11052 (comment)](https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329)). We plan to re-introduce this fix behind a future flag in the next minor version. ([#&#8203;11078](https://github.com/remix-run/react-router/pull/11078)) - Updated dependencies: - `react-router@6.20.1` - `@remix-run/router@1.13.1` ### [`v6.20.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6200) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.19.0...react-router-dom@6.20.0) ##### Minor Changes - Export the `PathParam` type from the public API ([#&#8203;10719](https://github.com/remix-run/react-router/pull/10719)) ##### Patch Changes - Updated dependencies: - `react-router@6.20.0` - `@remix-run/router@1.13.0` ### [`v6.19.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6190) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.18.0...react-router-dom@6.19.0) ##### Minor Changes - Add `unstable_flushSync` option to `useNavigate`/`useSumbit`/`fetcher.load`/`fetcher.submit` to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#&#8203;11005](https://github.com/remix-run/react-router/pull/11005)) - Allow `unstable_usePrompt` to accept a `BlockerFunction` in addition to a `boolean` ([#&#8203;10991](https://github.com/remix-run/react-router/pull/10991)) ##### Patch Changes - Fix issue where a changing fetcher `key` in a `useFetcher` that remains mounted wasn't getting picked up ([#&#8203;11009](https://github.com/remix-run/react-router/pull/11009)) - Fix `useFormAction` which was incorrectly inheriting the `?index` query param from child route `action` submissions ([#&#8203;11025](https://github.com/remix-run/react-router/pull/11025)) - Fix `NavLink` `active` logic when `to` location has a trailing slash ([#&#8203;10734](https://github.com/remix-run/react-router/pull/10734)) - Updated dependencies: - `react-router@6.19.0` - `@remix-run/router@1.12.0` ### [`v6.18.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6180) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.17.0...react-router-dom@6.18.0) ##### Minor Changes - Add support for manual fetcher key specification via `useFetcher({ key: string })` so you can access the same fetcher instance from different components in your application without prop-drilling ([RFC](https://github.com/remix-run/remix/discussions/7698)) ([#&#8203;10960](https://github.com/remix-run/react-router/pull/10960)) - Fetcher keys are now also exposed on the fetchers returned from `useFetchers` so that they can be looked up by `key` - Add `navigate`/`fetcherKey` params/props to `useSumbit`/`Form` to support kicking off a fetcher submission under the hood with an optionally user-specified `key` ([#&#8203;10960](https://github.com/remix-run/react-router/pull/10960)) - Invoking a fetcher in this way is ephemeral and stateless - If you need to access the state of one of these fetchers, you will need to leverage `useFetcher({ key })` to look it up elsewhere ##### Patch Changes - Adds a fetcher context to `RouterProvider` that holds completed fetcher data, in preparation for the upcoming future flag that will change the fetcher persistence/cleanup behavior ([#&#8203;10961](https://github.com/remix-run/react-router/pull/10961)) - Fix the `future` prop on `BrowserRouter`, `HashRouter` and `MemoryRouter` so that it accepts a `Partial<FutureConfig>` instead of requiring all flags to be included. ([#&#8203;10962](https://github.com/remix-run/react-router/pull/10962)) - Updated dependencies: - `@remix-run/router@1.11.0` - `react-router@6.18.0` ### [`v6.17.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6170) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.16.0...react-router-dom@6.17.0) ##### Minor Changes - Add experimental support for the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) via `document.startViewTransition` to enable CSS animated transitions on SPA navigations in your application. ([#&#8203;10916](https://github.com/remix-run/react-router/pull/10916)) The simplest approach to enabling a View Transition in your React Router app is via the new `<Link unstable_viewTransition>` prop. This will cause the navigation DOM update to be wrapped in `document.startViewTransition` which will enable transitions for the DOM update. Without any additional CSS styles, you'll get a basic cross-fade animation for your page. If you need to apply more fine-grained styles for your animations, you can leverage the `unstable_useViewTransitionState` hook which will tell you when a transition is in progress and you can use that to apply classes or styles: ```jsx function ImageLink(to, src, alt) { let isTransitioning = unstable_useViewTransitionState(to); return ( <Link to={to} unstable_viewTransition> <img src={src} alt={alt} style={{ viewTransitionName: isTransitioning ? "image-expand" : "", }} /> </Link> ); } ``` You can also use the `<NavLink unstable_viewTransition>` shorthand which will manage the hook usage for you and automatically add a `transitioning` class to the `<a>` during the transition: ```css a.transitioning img { view-transition-name: "image-expand"; } ``` ```jsx <NavLink to={to} unstable_viewTransition> <img src={src} alt={alt} /> </NavLink> ``` For an example usage of View Transitions with React Router, check out [our fork](https://github.com/brophdawg11/react-router-records) of the [Astro Records](https://github.com/Charca/astro-records) demo. For more information on using the View Transitions API, please refer to the [Smooth and simple transitions with the View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) guide from the Google Chrome team. Please note, that because the `ViewTransition` API is a DOM API, we now export a specific `RouterProvider` from `react-router-dom` with this functionality. If you are importing `RouterProvider` from `react-router`, then it will not support view transitions. ([#&#8203;10928](https://github.com/remix-run/react-router/pull/10928) ##### Patch Changes - Log a warning and fail gracefully in `ScrollRestoration` when `sessionStorage` is unavailable ([#&#8203;10848](https://github.com/remix-run/react-router/pull/10848)) - Updated dependencies: - `@remix-run/router@1.10.0` - `react-router@6.17.0` ### [`v6.16.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6160) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.15.0...react-router-dom@6.16.0) ##### Minor Changes - Updated dependencies: - `@remix-run/router@1.9.0` - `react-router@6.16.0` ##### Patch Changes - Properly encode rendered URIs in server rendering to avoid hydration errors ([#&#8203;10769](https://github.com/remix-run/react-router/pull/10769)) ### [`v6.15.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6150) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.14.2...react-router-dom@6.15.0) ##### Minor Changes - Add's a new `redirectDocument()` function which allows users to specify that a redirect from a `loader`/`action` should trigger a document reload (via `window.location`) instead of attempting to navigate to the redirected location via React Router ([#&#8203;10705](https://github.com/remix-run/react-router/pull/10705)) ##### Patch Changes - Fixes an edge-case affecting web extensions in Firefox that use `URLSearchParams` and the `useSearchParams` hook. ([#&#8203;10620](https://github.com/remix-run/react-router/pull/10620)) - Do not include hash in `useFormAction()` for unspecified actions since it cannot be determined on the server and causes hydration issues ([#&#8203;10758](https://github.com/remix-run/react-router/pull/10758)) - Reorder effects in `unstable_usePrompt` to avoid throwing an exception if the prompt is unblocked and a navigation is performed synchronously ([#&#8203;10687](https://github.com/remix-run/react-router/pull/10687), [#&#8203;10718](https://github.com/remix-run/react-router/pull/10718)) - Updated dependencies: - `@remix-run/router@1.8.0` - `react-router@6.15.0` ### [`v6.14.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6142) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.14.1...react-router-dom@6.14.2) ##### Patch Changes - Properly decode element id when emulating hash scrolling via `<ScrollRestoration>` ([#&#8203;10682](https://github.com/remix-run/react-router/pull/10682)) - Add missing `<Form state>` prop to populate `history.state` on submission navigations ([#&#8203;10630](https://github.com/remix-run/react-router/pull/10630)) - Support proper hydration of `Error` subclasses such as `ReferenceError`/`TypeError` ([#&#8203;10633](https://github.com/remix-run/react-router/pull/10633)) - Updated dependencies: - `@remix-run/router@1.7.2` - `react-router@6.14.2` ### [`v6.14.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6141) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.14.0...react-router-dom@6.14.1) ##### Patch Changes - Updated dependencies: - `react-router@6.14.1` - `@remix-run/router@1.7.1` ### [`v6.14.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6140) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.13.0...react-router-dom@6.14.0) ##### Minor Changes - Add support for `application/json` and `text/plain` encodings for `useSubmit`/`fetcher.submit`. To reflect these additional types, `useNavigation`/`useFetcher` now also contain `navigation.json`/`navigation.text` and `fetcher.json`/`fetcher.text` which include the json/text submission if applicable ([#&#8203;10413](https://github.com/remix-run/react-router/pull/10413)) ```jsx // The default behavior will still serialize as FormData function Component() { let navigation = useNavigation(); let submit = useSubmit(); submit({ key: "value" }, { method: "post" }); // navigation.formEncType => "application/x-www-form-urlencoded" // navigation.formData => FormData instance } async function action({ request }) { // request.headers.get("Content-Type") => "application/x-www-form-urlencoded" // await request.formData() => FormData instance } ``` ```js // Opt-into JSON encoding with `encType: "application/json"` function Component() { let navigation = useNavigation(); let submit = useSubmit(); submit({ key: "value" }, { method: "post", encType: "application/json" }); // navigation.formEncType => "application/json" // navigation.json => { key: "value" } } async function action({ request }) { // request.headers.get("Content-Type") => "application/json" // await request.json() => { key: "value" } } ``` ```js // Opt-into text encoding with `encType: "text/plain"` function Component() { let navigation = useNavigation(); let submit = useSubmit(); submit("Text submission", { method: "post", encType: "text/plain" }); // navigation.formEncType => "text/plain" // navigation.text => "Text submission" } async function action({ request }) { // request.headers.get("Content-Type") => "text/plain" // await request.text() => "Text submission" } ``` ##### Patch Changes - When submitting a form from a `submitter` element, prefer the built-in `new FormData(form, submitter)` instead of the previous manual approach in modern browsers (those that support the new `submitter` parameter) ([#&#8203;9865](https://github.com/remix-run/react-router/pull/9865), [#&#8203;10627](https://github.com/remix-run/react-router/pull/10627)) - For browsers that don't support it, we continue to just append the submit button's entry to the end, and we also add rudimentary support for `type="image"` buttons - If developers want full spec-compliant support for legacy browsers, they can use the `formdata-submitter-polyfill` - Call `window.history.pushState/replaceState` before updating React Router state (instead of after) so that `window.location` matches `useLocation` during synchronous React 17 rendering ([#&#8203;10448](https://github.com/remix-run/react-router/pull/10448)) - ⚠️ However, generally apps should not be relying on `window.location` and should always reference `useLocation` when possible, as `window.location` will not be in sync 100% of the time (due to `popstate` events, concurrent mode, etc.) - Fix `tsc --skipLibCheck:false` issues on React 17 ([#&#8203;10622](https://github.com/remix-run/react-router/pull/10622)) - Upgrade `typescript` to 5.1 ([#&#8203;10581](https://github.com/remix-run/react-router/pull/10581)) - Updated dependencies: - `react-router@6.14.0` - `@remix-run/router@1.7.0` ### [`v6.13.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6130) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.12.1...react-router-dom@6.13.0) ##### Minor Changes - Move [`React.startTransition`](https://react.dev/reference/react/startTransition) usage behind a [future flag](https://reactrouter.com/en/main/guides/api-development-strategy) to avoid issues with existing incompatible `Suspense` usages. We recommend folks adopting this flag to be better compatible with React concurrent mode, but if you run into issues you can continue without the use of `startTransition` until v7. Issues usually boils down to creating net-new promises during the render cycle, so if you run into issues you should either lift your promise creation out of the render cycle or put it behind a `useMemo`. ([#&#8203;10596](https://github.com/remix-run/react-router/pull/10596)) Existing behavior will no longer include `React.startTransition`: ```jsx <BrowserRouter> <Routes>{/*...*/}</Routes> </BrowserRouter> <RouterProvider router={router} /> ``` If you wish to enable `React.startTransition`, pass the future flag to your component: ```jsx <BrowserRouter future={{ v7_startTransition: true }}> <Routes>{/*...*/}</Routes> </BrowserRouter> <RouterProvider router={router} future={{ v7_startTransition: true }}/> ``` ##### Patch Changes - Work around webpack/terser `React.startTransition` minification bug in production mode ([#&#8203;10588](https://github.com/remix-run/react-router/pull/10588)) - Updated dependencies: - `react-router@6.13.0` ### [`v6.12.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6121) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.12.0...react-router-dom@6.12.1) > \[!WARNING] > Please use version `6.13.0` or later instead of `6.12.1`. This version suffers from a `webpack`/`terser` minification issue resulting in invalid minified code in your resulting production bundles which can cause issues in your application. See [#&#8203;10579](https://github.com/remix-run/react-router/issues/10579) for more details. ##### Patch Changes - Adjust feature detection of `React.startTransition` to fix webpack + react 17 compilation error ([#&#8203;10569](https://github.com/remix-run/react-router/pull/10569)) - Updated dependencies: - `react-router@6.12.1` ### [`v6.12.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6120) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.11.2...react-router-dom@6.12.0) ##### Minor Changes - Wrap internal router state updates with `React.startTransition` if it exists ([#&#8203;10438](https://github.com/remix-run/react-router/pull/10438)) ##### Patch Changes - Re-throw `DOMException` (`DataCloneError`) when attempting to perform a `PUSH` navigation with non-serializable state. ([#&#8203;10427](https://github.com/remix-run/react-router/pull/10427)) - Updated dependencies: - `@remix-run/router@1.6.3` - `react-router@6.12.0` ### [`v6.11.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6112) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.11.1...react-router-dom@6.11.2) ##### Patch Changes - Export `SetURLSearchParams` type ([#&#8203;10444](https://github.com/remix-run/react-router/pull/10444)) - Updated dependencies: - `react-router@6.11.2` - `@remix-run/router@1.6.2` ### [`v6.11.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6111) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.11.0...react-router-dom@6.11.1) ##### Patch Changes - Updated dependencies: - `react-router@6.11.1` - `@remix-run/router@1.6.1` ### [`v6.11.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6110) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.10.0...react-router-dom@6.11.0) ##### Minor Changes - Enable `basename` support in `useFetcher` ([#&#8203;10336](https://github.com/remix-run/react-router/pull/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')`) ##### Patch Changes - Fix inadvertent re-renders when using `Component` instead of `element` on a route definition ([#&#8203;10287](https://github.com/remix-run/react-router/pull/10287)) - Fail gracefully on `<Link to="//">` and other invalid URL values ([#&#8203;10367](https://github.com/remix-run/react-router/pull/10367)) - Switched from `useSyncExternalStore` to `useState` for internal `@remix-run/router` router state syncing in `<RouterProvider>`. We found some [subtle bugs](https://codesandbox.io/s/use-sync-external-store-loop-9g7b81) where router state updates got propagated *before* other normal `useState` updates, which could lead to footguns in `useEffect` calls. ([#&#8203;10377](https://github.com/remix-run/react-router/pull/10377), [#&#8203;10409](https://github.com/remix-run/react-router/pull/10409)) - Add static prop to `StaticRouterProvider`'s internal `Router` component ([#&#8203;10401](https://github.com/remix-run/react-router/pull/10401)) - 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()`. When using `BrowserRouter`, these hooks remain unstable across location changes because they still rely on `useLocation()`. ([#&#8203;10336](https://github.com/remix-run/react-router/pull/10336)) - Updated dependencies: - `react-router@6.11.0` - `@remix-run/router@1.6.0` ### [`v6.10.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;6100) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.9.0...react-router-dom@6.10.0) ##### Minor Changes - Added support for [**Future Flags**](https://reactrouter.com/en/main/guides/api-development-strategy) in React Router. The first 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()` behavior. ([#&#8203;10207](https://github.com/remix-run/react-router/pull/10207)) - When `future.v7_normalizeFormMethod === 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` ([#&#8203;10190](https://github.com/remix-run/react-router/pull/10190)) - Updated dependencies: - `@remix-run/router@1.5.0` - `react-router@6.10.0` ### [`v6.9.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;690) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.8.2...react-router-dom@6.9.0) ##### 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". ([#&#8203;10045](https://github.com/remix-run/react-router/pull/10045)) **Example JSON Syntax** ```jsx // 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** ```jsx // 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!** ([#&#8203;10045](https://github.com/remix-run/react-router/pull/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. ```jsx // 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: ```jsx 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`](https://github.com/remix-run/react-router/tree/main/examples/lazy-loading-router-provider) directory of the repository. 🙌 Huge thanks to [@&#8203;rossipedia](https://github.com/rossipedia) for the [Initial Proposal](https://github.com/remix-run/react-router/discussions/9826) and [POC Implementation](https://github.com/remix-run/react-router/pull/9830). - Updated dependencies: - `react-router@6.9.0` - `@remix-run/router@1.4.0` ### [`v6.8.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;682) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.8.1...react-router-dom@6.8.2) ##### Patch Changes - Treat same-origin absolute URLs in `<Link to>` as external if they are outside of the router `basename` ([#&#8203;10135](https://github.com/remix-run/react-router/pull/10135)) - Fix `useBlocker` to return `IDLE_BLOCKER` during SSR ([#&#8203;10046](https://github.com/remix-run/react-router/pull/10046)) - Fix SSR of absolute `<Link to>` urls ([#&#8203;10112](https://github.com/remix-run/react-router/pull/10112)) - Properly escape HTML characters in `StaticRouterProvider` serialized hydration data ([#&#8203;10068](https://github.com/remix-run/react-router/pull/10068)) - Updated dependencies: - `@remix-run/router@1.3.3` - `react-router@6.8.2` ### [`v6.8.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;681) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.8.0...react-router-dom@6.8.1) ##### Patch Changes - Improved absolute url detection in `Link` component (now also supports `mailto:` urls) ([#&#8203;9994](https://github.com/remix-run/react-router/pull/9994)) - Fix partial object (search or hash only) pathnames losing current path value ([#&#8203;10029](https://github.com/remix-run/react-router/pull/10029)) - Updated dependencies: - `react-router@6.8.1` - `@remix-run/router@1.3.2` ### [`v6.8.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;680) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.7.0...react-router-dom@6.8.0) ##### Minor Changes - Support absolute URLs in `<Link to>`. If the URL is for the current origin, it will still do a client-side navigation. If the URL is for a different origin then it will do a fresh document request for the new origin. ([#&#8203;9900](https://github.com/remix-run/react-router/pull/9900)) ```tsx <Link to="https://neworigin.com/some/path"> {/* Document request */} <Link to="//neworigin.com/some/path"> {/* Document request */} <Link to="https://www.currentorigin.com/path"> {/* Client-side navigation */} ``` ##### Patch Changes - Fix bug with search params removal via `useSearchParams` ([#&#8203;9969](https://github.com/remix-run/react-router/pull/9969)) - Respect `preventScrollReset` on `<fetcher.Form>` ([#&#8203;9963](https://github.com/remix-run/react-router/pull/9963)) - Fix navigation for hash routers on manual URL changes ([#&#8203;9980](https://github.com/remix-run/react-router/pull/9980)) - Use `pagehide` instead of `beforeunload` for `<ScrollRestoration>`. This has better cross-browser support, specifically on Mobile Safari. ([#&#8203;9945](https://github.com/remix-run/react-router/pull/9945)) - Updated dependencies: - `@remix-run/router@1.3.1` - `react-router@6.8.0` ### [`v6.7.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;670) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.6.2...react-router-dom@6.7.0) ##### Minor Changes - Add `unstable_useBlocker` hook for blocking navigations within the app's location origin ([#&#8203;9709](https://github.com/remix-run/react-router/pull/9709)) - Add `unstable_usePrompt` hook for blocking navigations within the app's location origin ([#&#8203;9932](https://github.com/remix-run/react-router/pull/9932)) - Add `preventScrollReset` prop to `<Form>` ([#&#8203;9886](https://github.com/remix-run/react-router/pull/9886)) ##### Patch Changes - Added pass-through event listener options argument to `useBeforeUnload` ([#&#8203;9709](https://github.com/remix-run/react-router/pull/9709)) - Streamline jsdom bug workaround in tests ([#&#8203;9824](https://github.com/remix-run/react-router/pull/9824)) - Updated dependencies: - `@remix-run/router@1.3.0` - `react-router@6.7.0` ### [`v6.6.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;662) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.6.1...react-router-dom@6.6.2) ##### Patch Changes - Ensure `useId` consistency during SSR ([#&#8203;9805](https://github.com/remix-run/react-router/pull/9805)) - Updated dependencies: - `react-router@6.6.2` ### [`v6.6.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;661) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.6.0...react-router-dom@6.6.1) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.2.1` - `react-router@6.6.1` ### [`v6.6.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;660) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.5.0...react-router-dom@6.6.0) ##### Minor Changes - Add `useBeforeUnload()` hook ([#&#8203;9664](https://github.com/remix-run/react-router/pull/9664)) - Remove `unstable_` prefix from `createStaticHandler`/`createStaticRouter`/`StaticRouterProvider` ([#&#8203;9738](https://github.com/remix-run/react-router/pull/9738)) ##### Patch Changes - Proper hydration of `Error` objects from `StaticRouterProvider` ([#&#8203;9664](https://github.com/remix-run/react-router/pull/9664)) - Support uppercase `<Form method>` and `useSubmit` method values ([#&#8203;9664](https://github.com/remix-run/react-router/pull/9664)) - Skip initial scroll restoration for SSR apps with `hydrationData` ([#&#8203;9664](https://github.com/remix-run/react-router/pull/9664)) - Fix `<button formmethod>` form submission overriddes ([#&#8203;9664](https://github.com/remix-run/react-router/pull/9664)) - Updated dependencies: - `@remix-run/router@1.2.0` - `react-router@6.6.0` ### [`v6.5.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;650) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.4.5...react-router-dom@6.5.0) ##### Patch Changes - Updated dependencies: - `react-router@6.5.0` - `@remix-run/router@1.1.0` ### [`v6.4.5`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;645) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.4.4...react-router-dom@6.4.5) ##### Patch Changes - Updated dependencies: - `@remix-run/router@1.0.5` - `react-router@6.4.5` ### [`v6.4.4`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;644) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.4.3...react-router-dom@6.4.4) ##### Patch Changes - Fix issues with encoded characters in `NavLink` and descendant `<Routes>` ([#&#8203;9589](https://github.com/remix-run/react-router/pull/9589), [#&#8203;9647](https://github.com/remix-run/react-router/pull/9647)) - Properly serialize/deserialize `ErrorResponse` instances when using built-in hydration ([#&#8203;9593](https://github.com/remix-run/react-router/pull/9593)) - Support `basename` in static data routers ([#&#8203;9591](https://github.com/remix-run/react-router/pull/9591)) - Updated dependencies: - `@remix-run/router@1.0.4` - `react-router@6.4.4` ### [`v6.4.3`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;643) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.4.2...react-router-dom@6.4.3) ##### Patch Changes - Fix hrefs generated for `createHashRouter` ([#&#8203;9409](https://github.com/remix-run/react-router/pull/9409)) - fix encoding/matching issues with special chars ([#&#8203;9477](https://github.com/remix-run/react-router/pull/9477), [#&#8203;9496](https://github.com/remix-run/react-router/pull/9496)) - Properly support `index` routes with a `path` in `useResolvedPath` ([#&#8203;9486](https://github.com/remix-run/react-router/pull/9486)) - Respect `relative=path` prop on `NavLink` ([#&#8203;9453](https://github.com/remix-run/react-router/pull/9453)) - Fix `NavLink` behavior for root urls ([#&#8203;9497](https://github.com/remix-run/react-router/pull/9497)) - Updated dependencies: - `@remix-run/router@1.0.3` - `react-router@6.4.3` ### [`v6.4.2`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;642) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.4.1...react-router-dom@6.4.2) ##### Patch Changes - Respect `basename` in `useFormAction` ([#&#8203;9352](https://github.com/remix-run/react-router/pull/9352)) - Enhance console error messages for invalid usage of data router hooks ([#&#8203;9311](https://github.com/remix-run/react-router/pull/9311)) - If an index route has children, it will result in a runtime error. We have strengthened our `RouteObject`/`RouteProps` types to surface the error in TypeScript. ([#&#8203;9366](https://github.com/remix-run/react-router/pull/9366)) - Updated dependencies: - `react-router@6.4.2` - `@remix-run/router@1.0.2` ### [`v6.4.1`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;641) [Compare Source](https://github.com/remix-run/react-router/compare/react-router-dom@6.4.0...react-router-dom@6.4.1) ##### Patch Changes - Updated dependencies: - `react-router@6.4.1` - `@remix-run/router@1.0.1` ### [`v6.4.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#&#8203;640) [Compare Source](https://github.com/remix-run/react-router/compare/v6.3.0...react-router-dom@6.4.0) Whoa this is a big one! `6.4.0` brings all the data loading and mutation APIs over from Remix. Here's a quick high level overview, but it's recommended you go check out the [docs](https://reactrouter.com), especially the [feature overview](https://reactrouter.com/start/overview) and the [tutorial](https://reactrouter.com/start/tutorial). **New APIs** - Create your router with `createMemoryRouter`/`createBrowserRouter`/`createHashRouter` - Render your router with `<RouterProvider>` - Load data with a Route `loader` and mutate with a Route `action` - Handle errors with Route `errorElement` - Submit data with the new `<Form>` component - Perform in-page data loads and mutations with `useFetcher()` - Defer non-critical data with `defer` and `Await` - Manage scroll position with `<ScrollRestoration>` **New Features** - Perform path-relative navigations with `<Link relative="path">` ([#&#8203;9160](https://github.com/remix-run/react-router/issues/9160)) **Bug Fixes** - Path resolution is now trailing slash agnostic ([#&#8203;8861](https://github.com/remix-run/react-router/issues/8861)) - `useLocation` returns the scoped location inside a `<Routes location>` component ([#&#8203;9094](https://github.com/remix-run/react-router/issues/9094)) - respect the `<Link replace>` prop if it is defined ([#&#8203;8779](https://github.com/remix-run/react-router/issues/8779)) **Updated Dependencies** - `react-router@6.4.0` ### [`v6.3.0`](https://github.com/remix-run/react-router/releases/tag/v6.3.0): react-router@v6.3.0 [Compare Source](https://github.com/remix-run/react-router/compare/v6.2.2...v6.3.0) ##### What's Changed - Added the v5 to v6 backwards compatibility package 💜 (https://github.com/remix-run/react-router/pull/8752). The official guide can be found [in this discussion](https://github.com/remix-run/react-router/discussions/8753) ##### New Contributors - [@&#8203;mfijas](https://github.com/mfijas) made their first contribution in https://github.com/remix-run/react-router/pull/8717 - [@&#8203;ThornWu](https://github.com/ThornWu) made their first contribution in https://github.com/remix-run/react-router/pull/8718 - [@&#8203;janpaepke](https://github.com/janpaepke) made their first contribution in https://github.com/remix-run/react-router/pull/8651 - [@&#8203;rtmann](https://github.com/rtmann) made their first contribution in https://github.com/remix-run/react-router/pull/8725 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.2.2...v6.3.0 ### [`v6.2.2`](https://github.com/remix-run/react-router/releases/tag/v6.2.2) [Compare Source](https://github.com/remix-run/react-router/compare/v6.2.1...v6.2.2) #### What's Changed ##### 🐛 Bug Fixes - Fixed nested splat routes that begin with special URL-safe characters ([#&#8203;8563](https://github.com/remix-run/react-router/issues/8563)) - Fixed a bug where index routes were missing route context in some cases ([#&#8203;8497](https://github.com/remix-run/react-router/issues/8497)) #### New Contributors - [@&#8203;chasinhues](https://github.com/chasinhues) made their first contribution in https://github.com/remix-run/react-router/pull/8514 - [@&#8203;underager](https://github.com/underager) made their first contribution in https://github.com/remix-run/react-router/pull/8531 - [@&#8203;kantuni](https://github.com/kantuni) made their first contribution in https://github.com/remix-run/react-router/pull/8537 - [@&#8203;ArjaanBuijk](https://github.com/ArjaanBuijk) made their first contribution in https://github.com/remix-run/react-router/pull/8536 - [@&#8203;jmargeta](https://github.com/jmargeta) made their first contribution in https://github.com/remix-run/react-router/pull/8548 - [@&#8203;koojaa](https://github.com/koojaa) made their first contribution in https://github.com/remix-run/react-router/pull/8542 - [@&#8203;chrisngobanh](https://github.com/chrisngobanh) made their first contribution in https://github.com/remix-run/react-router/pull/8576 - [@&#8203;ChristopherChudzicki](https://github.com/ChristopherChudzicki) made their first contribution in https://github.com/remix-run/react-router/pull/8582 - [@&#8203;awreese](https://github.com/awreese) made their first contribution in https://github.com/remix-run/react-router/pull/8596 - [@&#8203;bhbs](https://github.com/bhbs) made their first contribution in https://github.com/remix-run/react-router/pull/8601 - [@&#8203;LukerSpringtree](https://github.com/LukerSpringtree) made their first contribution in https://github.com/remix-run/react-router/pull/8619 - [@&#8203;hsbtr](https://github.com/hsbtr) made their first contribution in https://github.com/remix-run/react-router/pull/8476 - [@&#8203;abhi-kr-2100](https://github.com/abhi-kr-2100) made their first contribution in https://github.com/remix-run/react-router/pull/8658 - [@&#8203;cvbuelow](https://github.com/cvbuelow) made their first contribution in https://github.com/remix-run/react-router/pull/8663 - [@&#8203;hyesungoh](https://github.com/hyesungoh) made their first contribution in https://github.com/remix-run/react-router/pull/8666 - [@&#8203;BrianT1414](https://github.com/BrianT1414) made their first contribution in https://github.com/remix-run/react-router/pull/8667 - [@&#8203;IbraRouisDev](https://github.com/IbraRouisDev) made their first contribution in https://github.com/remix-run/react-router/pull/8683 - [@&#8203;shihanng](https://github.com/shihanng) made their first contribution in https://github.com/remix-run/react-router/pull/8689 - [@&#8203;latin-1](https://github.com/latin-1) made their first contribution in https://github.com/remix-run/react-router/pull/8529 - [@&#8203;Isammoc](https://github.com/Isammoc) made their first contribution in https://github.com/remix-run/react-router/pull/8533 - [@&#8203;KutnerUri](https://github.com/KutnerUri) made their first contribution in https://github.com/remix-run/react-router/pull/8278 - [@&#8203;shamsup](https://github.com/shamsup) made their first contribution in https://github.com/remix-run/react-router/pull/8563 - [@&#8203;brophdawg11](https://github.com/brophdawg11) made their first contribution in https://github.com/remix-run/react-router/pull/8691 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.2.1...v6.2.2 ### [`v6.2.1`](https://github.com/remix-run/react-router/releases/tag/v6.2.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.2.0...v6.2.1) This release updates the internal `history` dependency to `5.2.0`. **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.2.0...v6.2.1 ### [`v6.2.0`](https://github.com/remix-run/react-router/releases/tag/v6.2.0) [Compare Source](https://github.com/remix-run/react-router/compare/v6.1.1...v6.2.0) ##### 🐛 Bug fixes - Fixed the `RouteProps` `element` type, which should be a `ReactNode` ([#&#8203;8473](https://github.com/remix-run/react-router/issues/8473)) - Fixed a bug with `useOutlet` for top-level routes ([#&#8203;8483](https://github.com/remix-run/react-router/issues/8483)) ##### ✨ Features - We now use statically analyzable CJS exports. This enables named imports in Node ESM scripts ([See the commit](https://github.com/remix-run/react-router/commit/29c7fc8b5f853b0b06ecd0f5682a9bbe6eca0715)). ##### New Contributors - [@&#8203;thisiskartik](https://github.com/thisiskartik) made their first contribution in https://github.com/remix-run/react-router/pull/8487 - [@&#8203;vijaypushkin](https://github.com/vijaypushkin) made their first contribution in https://github.com/remix-run/react-router/pull/8491 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.1.1...v6.2.0 ### [`v6.1.1`](https://github.com/remix-run/react-router/releases/tag/v6.1.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.1.0...v6.1.1) In v6.1.0 we inadvertently shipped a new, undocumented API that will likely introduce bugs ([#&#8203;7586](https://github.com/remix-run/react-router/issues/7586)). We have flagged `HistoryRouter` as `unstable_HistoryRouter`, as this API will likely need to change before a new major release. **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.1.0...v6.1.1 ### [`v6.1.0`](https://github.com/remix-run/react-router/releases/tag/v6.1.0) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.2...v6.1.0) ##### 🐛 Bug fixes - Fixed a bug that broke support for base64 encoded IDs on nested routes ([#&#8203;8291](https://github.com/remix-run/react-router/issues/8291)) ##### ✨ Features - `<Outlet>` can now receive a `context` prop. This value is passed to child routes and is accessible via the new `useOutletContext` hook. See [the API docs](https://reactrouter.com/docs/en/v6/api#useoutletcontext) for details. ([#&#8203;8461](https://github.com/remix-run/react-router/issues/8461)) - `<NavLink>` can now receive a child function for access to its props. ([#&#8203;8164](https://github.com/remix-run/react-router/issues/8164)) ##### 💅 Enhancements - Improved TypeScript signature for `useMatch` and `matchPath`. For example, when you call `useMatch("foo/:bar/:baz")`, the path is parsed and the return type will be `PathMatch<"bar" | "baz">`. ([#&#8203;8030](https://github.com/remix-run/react-router/issues/8030)) - A few error message improvements ([#&#8203;8202](https://github.com/remix-run/react-router/issues/8202)) ##### New Contributors - [@&#8203;rwieruch](https://github.com/rwieruch) made their first contribution in https://github.com/remix-run/react-router/pull/8244 - [@&#8203;codeiotic](https://github.com/codeiotic) made their first contribution in https://github.com/remix-run/react-router/pull/8247 - [@&#8203;Sannnao](https://github.com/Sannnao) made their first contribution in https://github.com/remix-run/react-router/pull/8263 - [@&#8203;mattmazzola](https://github.com/mattmazzola) made their first contribution in https://github.com/remix-run/react-router/pull/8255 - [@&#8203;ngokevin](https://github.com/ngokevin) made their first contribution in https://github.com/remix-run/react-router/pull/8267 - [@&#8203;TimisRobert](https://github.com/TimisRobert) made their first contribution in https://github.com/remix-run/react-router/pull/8269 - [@&#8203;mikeldking](https://github.com/mikeldking) made their first contribution in https://github.com/remix-run/react-router/pull/8279 - [@&#8203;fishmandev](https://github.com/fishmandev) made their first contribution in https://github.com/remix-run/react-router/pull/8289 - [@&#8203;rjerue](https://github.com/rjerue) made their first contribution in https://github.com/remix-run/react-router/pull/8304 - [@&#8203;rockingskier](https://github.com/rockingskier) made their first contribution in https://github.com/remix-run/react-router/pull/8314 - [@&#8203;arinthros](https://github.com/arinthros) made their first contribution in https://github.com/remix-run/react-router/pull/8337 - [@&#8203;noisypigeon](https://github.com/noisypigeon) made their first contribution in https://github.com/remix-run/react-router/pull/8361 - [@&#8203;elylucas](https://github.com/elylucas) made their first contribution in https://github.com/remix-run/react-router/pull/8368 - [@&#8203;paulsmithkc](https://github.com/paulsmithkc) made their first contribution in https://github.com/remix-run/react-router/pull/8357 - [@&#8203;sanketshah19](https://github.com/sanketshah19) made their first contribution in https://github.com/remix-run/react-router/pull/8372 - [@&#8203;JakubDrozd](https://github.com/JakubDrozd) made their first contribution in https://github.com/remix-run/react-router/pull/8402 - [@&#8203;markivancho](https://github.com/markivancho) made their first contribution in https://github.com/remix-run/react-router/pull/8414 - [@&#8203;turansky](https://github.com/turansky) made their first contribution in https://github.com/remix-run/react-router/pull/8420 - [@&#8203;shivamsinghchahar](https://github.com/shivamsinghchahar) made their first contribution in https://github.com/remix-run/react-router/pull/8423 - [@&#8203;petersendidit](https://github.com/petersendidit) made their first contribution in https://github.com/remix-run/react-router/pull/8436 - [@&#8203;Ajayff4](https://github.com/Ajayff4) made their first contribution in https://github.com/remix-run/react-router/pull/8373 - [@&#8203;RobHannay](https://github.com/RobHannay) made their first contribution in https://github.com/remix-run/react-router/pull/8455 - [@&#8203;kddnewton](https://github.com/kddnewton) made their first contribution in https://github.com/remix-run/react-router/pull/8030 - [@&#8203;brockross](https://github.com/brockross) made their first contribution in https://github.com/remix-run/react-router/pull/8462 - [@&#8203;sergiodxa](https://github.com/sergiodxa) made their first contribution in https://github.com/remix-run/react-router/pull/8164 - [@&#8203;baozouai](https://github.com/baozouai) made their first contribution in https://github.com/remix-run/react-router/pull/8171 - [@&#8203;liuhanqu](https://github.com/liuhanqu) made their first contribution in https://github.com/remix-run/react-router/pull/8374 **Full Changelog**: https://github.com/remix-run/react-router/compare/v6.0.1...v6.1.0 ### [`v6.0.2`](https://github.com/remix-run/react-router/releases/tag/v6.0.2) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.1...v6.0.2) ##### ✨ Features - Added the `reloadDocument` prop to `<Link>`. This allows `<Link>` to function like a normal anchor tag by reloading the document after navigation while maintaining the relative `to` resolution. ##### 🗒️ Docs - Fixed several issues in docblocks and the docs themselves. See the [full changelog](https://github.com/remix-run/react-router/compare/v6.0.1...v6.0.2) for the deets! ##### 🤝 New Contributors - [@&#8203;rwieruch](https://github.com/rwieruch) made their first contribution in https://github.com/remix-run/react-router/pull/8244 - [@&#8203;ProProgrammer2504](https://github.com/ProProgrammer2504) made their first contribution in https://github.com/remix-run/react-router/pull/8247 - [@&#8203;Sannnao](https://github.com/Sannnao) made their first contribution in https://github.com/remix-run/react-router/pull/8263 - [@&#8203;mattmazzola](https://github.com/mattmazzola) made their first contribution in https://github.com/remix-run/react-router/pull/8255 - [@&#8203;ngokevin](https://github.com/ngokevin) made their first contribution in https://github.com/remix-run/react-router/pull/8267 - [@&#8203;TimisRobert](https://github.com/TimisRobert) made their first contribution in https://github.com/remix-run/react-router/pull/8269 - [@&#8203;mikeldking](https://github.com/mikeldking) made their first contribution in https://github.com/remix-run/react-router/pull/8279 - [@&#8203;fishmandev](https://github.com/fishmandev) made their first contribution in https://github.com/remix-run/react-router/pull/8289 ##### Full Changelog ### [`v6.0.1`](https://github.com/remix-run/react-router/releases/tag/v6.0.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0...v6.0.1) ##### 🐛 Bug Fixes - Add a default `<StaticRouter location>` value ([#&#8203;8243](https://github.com/remix-run/react-router/issues/8243)) - Add invariant for using `<Route>` inside `<Routes>` to help people make the change ([#&#8203;8238](https://github.com/remix-run/react-router/issues/8238)) ### [`v6.0.0`](https://github.com/remix-run/react-router/releases/tag/v6.0.0) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.8...v6.0.0) React Router v6 is here! Please go read [our blog post for more information on all the great stuff in v6](https://remix.run/blog/react-router-v6) including [notes about how to upgrade from React Router v5](https://remix.run/blog/react-router-v6#upgrading-to-react-router-v6) and Reach Router. ### [`v6.0.0-beta.8`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.8) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.7...v6.0.0-beta.8) Remember last week when we said > We anticipate this will be the last beta release before v6 stable next week. Yeah, about that … 😅 We found and squashed a few high-priority bugs that needed to be addressed first. But it's coming very soon, we promise! In the mean time, here's what you'll get from our eight-est and greatest beta release: ##### 🐛 Bug Fixes - We fixed a few bugs in `useHref` that resulted in the incorrect resolved value in cases where a `basename` is used on the `<Router />` component (See [#&#8203;8133](https://github.com/remix-run/react-router/issues/8133) and [#&#8203;8142](https://github.com/remix-run/react-router/issues/8142) for details). - We also fixed a bug in our path ranking algorithm so that splat routes (routes with a `*` path value) are now correctly ranked ahead of layout routes. ##### 🗒️ Docs We've added lots of goodies to our `docs` and `examples`, and there's a lot more yet to come. Take a look and see if you find something that makes your work a little easier! We think the [lazy loading](https://github.com/remix-run/react-router/tree/dev/examples/lazy-loading) and [custom query parsing](https://github.com/remix-run/react-router/tree/dev/examples/custom-query-parsing) examples are particularly cool! 🤓 ### [`v6.0.0-beta.7`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.7) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.6...v6.0.0-beta.7) In this release we made a small but significant change to how `<Link to="..">` works. This is going to help out a lot if you were trying to use links in a `*` route. We have also backed out our blocking/prompt APIs for the stable v6 release. We will revisit this post 6.0 when we have a little more time to get it right. ##### ✨ Features The major change in this release could also be classified as a bugfix or a breaking change, depending on how you look at it. We essentialy altered the way `<Link to="..">` works. See [#&#8203;8086](https://github.com/remix-run/react-router/issues/8086) for the motivation behind this change. You'll probably want to reread [the section in the v5 => v6 migration guide about `<Link to>` values](https://github.com/remix-run/react-router/blob/main/docs/guides/migrating-5-to-6.md#note-on-link-to-values) (it has been updated), but it basically boils down to this: **any leading `..` segment in a `<Link to>` value traverses "up" one route and builds upon that route's path instead of just removing one URL segment**. This feature really completes the story of relative routes and links. We could consider this a bugfix, since this is how it was always intended to work in the first place. Without it, you'd have a difficult time linking predictably in `*` routes because your `<a href>` would be different depending on the number of segments in the current URL. The reason this could also be considered a breaking change is that `..` now works slightly differently in `<Link to>` than it would in `<a href>`. When you have `<a href="..">` it operates on the URL pathname, removing one segment of the current URL. However, since many routes really only match a single segment of the URL, there is often no difference between `<Link to="..">` and `<a href="..">`. ##### 💔 Breaking Changes - We removed `useBlocker()`, `usePrompt()`, and `<Prompt>` for now. We will revisit these post 6.0 when we have more time to get it right. But we don't want it to *block* (see what I did there) the release of all the other awesome stuff we've got in v6. ##### 🛠 Roadmap We anticipate this will be the last beta release before v6 stable next week. Please give it a shot and let us know how it goes! ##### 👍 Upgrading If you're thinking about upgrading to v6, I published a few notes this past week that may help you: - [This note talks about removing `<Redirect>` elements from any `<Switch>`es you may have in your v5 app](https://gist.github.com/mjackson/b5748add2795ce7448a366ae8f8ae3bb) and how you can get better SEO in the process if you're currently relying on client-side redirects. - [This note talks about how to refactor your code to avoid "wrapping" `<Route>` elements](https://gist.github.com/mjackson/d54b40a094277b7afdd6b81f51a0393f), which won't work in v6. Both of those posts contain steps you can take **today in your v5 app** without upgrading to v6. We are also developing a backwards compat lib that should help some of you upgrade from v5 to v6. We'll post more about this when it's ready. ##### 💻 Installing Development for v6 has switched from `dev` [to the `main` branch](https://github.com/remix-run/react-router/tree/main). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.6`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.6) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.5...v6.0.0-beta.6) No big enhancements in this release, just squashing bugs and writing lots of tests! Also, we are hard at work on cranking out examples for v6. See the end of this post for an update on our roadmap between here and v6 stable. ##### 🧰 Examples We have begun creating some examples for v6 that we hope will help developers make effective use of all the new features we have. So far, we have examples for the following: - [Basic Example](https://github.com/remix-run/react-router/tree/dev/examples/basic) – A basic client-side app for v6 showing how to use nested routes, layouts, links, and the new `<Outlet>` API - [Auth Example](https://github.com/remix-run/react-router/tree/dev/examples/auth) – Demonstrates an authentication flow including using the new `useNavigate()` hook, the `<Navigate>` element, and `location.state` - [Search Params Example](https://github.com/remix-run/react-router/tree/dev/examples/search-params) – Demonstrates how to build a simple search form that uses the new `useSearchParams()` hook - [SSR Example](https://github.com/remix-run/react-router/tree/dev/examples/ssr) – A server-rendered app that uses `<StaticRouter>` on the server and uses a `<BrowserRouter>` with `ReactDOM.hydrate()` on the client Each example includes a button in the README that allows you to instantly launch a running instance on StackBlitz that you can play with. We hope you enjoy exploring! ##### 🐛 Bugfixes - Make `<NavLink>` match only whole URL segments instead of pieces. This means that `<NavLink to="/home/users">` will still be active at `/home/users`, but not at `/home/users2`. See [#&#8203;7523](https://github.com/remix-run/react-router/issues/7523) - Makes "layout routes" (routes with no `path`) never match unless one of their children do. See [#&#8203;8085](https://github.com/remix-run/react-router/issues/8085) - Fixes a route matching regression with splat routes that was introduced in beta.5. See [#&#8203;8072](https://github.com/remix-run/react-router/issues/8072) and [#&#8203;8109](https://github.com/remix-run/react-router/issues/8109) - Fixes matching a nested splat route. See [`af7d038`](https://github.com/remix-run/react-router/commit/af7d038e) - Provide all parent route params to descendant `<Routes>`. This reverses a decision that we made in beta.5 to remove them. See [#&#8203;8073](https://github.com/remix-run/react-router/issues/8073) ##### 💔 Breaking Changes - Splats in route paths (`*`) match only after a `/` in the URL. This means that `<Route path="files*">` will always match as if it were `<Route path="files/*">`. The router will issue a warning if your route path ends with `*` but not `/*` ##### 🛠 Roadmap We are very close to a stable release! The last big code changes we need to make are: - Fixing "linking up". Currently a `<Link to="..">` operates on the URL pathname. However, this makes it difficult to link to the parent route when you're in a splat route. See [#&#8203;8086](https://github.com/remix-run/react-router/issues/8086). This will be a breaking change. - We are going to remove `useBlocker()` and `<Prompt>` in our initial v6 release, with plans to revisit them and possibly add them back at some point in the future. I still need to write up something here that explains our rationale. This will also be a breaking change. - We are going to add some animation primitives (see https://github.com/remix-run/react-router/discussions/8008). The `<Routes location>` prop will be in v6, but it isn't ideal for animation. ##### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.5`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.5) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.4...v6.0.0-beta.5) This week's release adds some much-needed polish to a few niche features of the router: splat routes (a route that uses a `*` path) and basenames. It also adds a `renderMatches` API that completes the story for those of you who may have been using `react-router-config` in v4 and v5. ##### 🐛 Bugfixes - A `*` in a child route path matches *after* a slash following its parent route path. This fixes some situations where the `*` was overly greedy (see [#&#8203;7972](https://github.com/remix-run/react-router/issues/7972)) - Resolution of `<Link to=".">` and `useResolvedPath(".")` values are fixed in splat routes. Previously these resolved relative to the parent route's path. They now resolve relative to the path of the route that rendered them. ##### ✨ Enhancements This release makes it easier to work with apps that have multiple entry points. Using the `<Router basename>` prop allows React Router to be easily deployed on only a portion of a larger site by using a portion of the URL pathname (the "basename") to transparently prefix all route paths and link navigations. For example, you can deploy one React Router app at the `/inbox` URL prefix, and another one at the `/admin` prefix. These base URLs represent two different entry points into your app, each with its own bundles. The rest of your site, including the root / URL could be rendered by something other than React Router, for example by your server framework of choice. In the bundle for each entry point, simply initialize React Router with the basename of that entry point. ```tsx <Router basename="/inbox"> // ... </Router> ``` Then define your routes and link paths without using the `/inbox` URL prefix in any of them. The entire app will run relative to that prefix. Another improvement in this release is the addition of the `renderMatches` API, which is the complement of `matchRoutes`. These APIs are both very low-level and should not normally be needed. But they are sometimes nice to use if you are doing your own data loading using the array of `matches` that you get back from `matchRoutes`. `matchRoutes` and `renderMatches` are the equivalent of the `react-router-config` package we shipped in v4 and v5, just built directly into the router instead of in a separate package. ##### 💔 Breaking Changes - `<Routes basename>` has moved to `<Router basename>`. This prop is also available on all router variants (`<BrowserRouter>`, `<HashRouter>`, etc.). - `useLocation().pathname` no longer includes the basename, if present. - The `basename` argument was removed from `useRoutes`. This reverts the signature to `useRoutes(routes, location)`, same as it was previous to beta.4. - Descendant `<Routes>` do not get the params from their parents. This helps a set of `<Routes>` to be more portable by decoupling it from the params of its parents and makes it easier to know which params will be returned from `useParams()`. If you were relying on this behavior previously, you'll need to pass along the params manually to the elements rendered by the descendant `<Routes>`. See [this comment](https://github.com/remix-run/react-router/issues/8073#issuecomment-929687218) for an example of how this is to be done and for a potential workaround if you really need the old behavior. - `match.pathname` in a splat route now includes the portion of the pathname matched by the `*`. This makes the `*` param behave much more like other dynamic `:id`-style params. - Resolution of relative `<Link>`s in splat routes is changed now because the entire pathname that was matched by that route is now different (see previous bullet). Instead of resolving relative to the portion of the pathname before the `*`, paths resolve relative to the full pathname that was matched by the route. ##### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.4`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.4) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.3...v6.0.0-beta.4) Last week we released a lot of nice little bug features, but we did get a little carried away and let a little bug slip through with relative path resolution. Our bad! That nasty lil' guy is squashed in this week's beta. 🐛 And there's more! Let's dive in… ##### 🐛 Bugfixes - Path resolution for nested relative routes was broken in the last release and should now be fixed. Nested routes construct their pathname based on the location of their parent, *not* the current location. This is explained in detail under [Relative Routes and Links in our advanced guides](docs/advanced-guides/migrating-5-to-6.md#relative-routes-and-links), and the issue itself in [#&#8203;8004](https://github.com/remix-run/react-router/issues/8004) ##### ✨ Enhancements - We made some enhancements with the `Params` type which is now generic, so you can add your own types if you know what to expect from functions that return query parameters. ([#&#8203;8019](https://github.com/remix-run/react-router/issues/8019)) ```tsx // before let { valid, invalid } = useParams(); // No problems here! let match = useMatch("profile/:userId"); let userId = match?.params.user; // wrong param, but TS doesn't know that! // after: let { valid, invalid } = useParams<"valid" | "key">(); // Property 'invalid' does not exist on type 'Params<"valid" | "key">' let match = useMatch<"userId">("profile/:userId"); let userId = match?.params.user; // Property 'user' does not exist on type 'Params<"userId">' ``` - Absolute nested path support There was quite a bit of discussion in [#&#8203;7335](https://github.com/remix-run/react-router/issues/7335) from people who are using constants to define their route paths. In this style, paths are often written as absolute paths from the root `/` URL. These constants are then able to be used both in `<Route path>` definitions as well as `<Link to>` values. It usually looks something like this: ```tsx const USERS_PATH = "/users"; const USERS_INDEX_PATH = `${USERS_PATH}/`; const USER_PROFILE_PATH = `${USERS_PATH}/:id`; function UsersRoutes() { return ( <Routes> <Route path={USERS_PATH} element={<UsersLayout />}> <Route path={USERS_INDEX_PATH} element={<UsersIndex />} /> <Route path={USER_PROFILE_PATH} element={<UserProfile />} /> </Route> </Routes> ); } ``` This style of use is now fully supported in v6. This is great for people who write their apps like this, but **it technically could cause some breakage** if you were using absolute paths (that start with `/`) in nested routes in previous betas. To fix this, simply **remove the `/` from the beginning of any route paths that are meant to be relative**. React Router will throw an error if you are using absolute paths that don't match their parent route paths. Hopefully this should help you find them if you are upgrading. If you were using `<Route path="/">` to indicate an index route, you can now use the new `<Route index>` prop to accomplish the same thing. The `index` prop makes it easy to scan a route config to find the index route. It also provides a guarantee that nobody will ever add children to that route. Here's the same route config as the one above, but rewritten with relative paths and the `index` prop: ```tsx function UsersRoutes() { return ( <Routes> <Route path="users" element={<UsersLayout />}> <Route index element={<UsersIndex />} /> <Route path=":id" element={<UserProfile />} /> </Route> </Routes> ); } ``` A lot of our work on React Router is about doing the **least surprising** thing for our users. Allowing absolute paths in nested routes gets us a little closer to that goal! ##### 💔 Breaking Changes - Removed the ability for nested route paths to begin with a `/` and not contain the complete path of their parent routes. This was necessary in order to introduce support for absolute paths in nested routes, described in detail above - Removed the `createRoutesFromArray` utility function. You can now pass your routes directly to `useRoutes` or `matchRoutes` without passing it through `createRoutesFromArray` first - Removed the `PartialRouteObject` type. If you were importing and using this type before, use `RouteObject` instead, which has been updated to make all properties optional - The `useRoutes` API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object: ```tsx // Before useRoutes([...routes], basename); // After useRoutes([...routes], { basename }); ``` - The `matchPath` function now returns `match.pattern` instead of `match.path`, which is a little more descriptive about what it actually is ##### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ### [`v6.0.0-beta.3`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.3) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.2...v6.0.0-beta.3) Loads of goodies for you this week, as well as a few breaking changes for all of you eager beavers who are brave enough to use beta software in production! 🦫 (seriously, thank you all for helping us tighten up our APIs and fix nasty bugs) ##### 💔 Breaking Changes! - `NavLink` no longer supports the `activeClassName` or `activeStyle` props. Instead, we provide a more powerful API that allows you to pass functions to either the `className` or `style` props to conditionally apply values based on the link's `active` state. While a bit more verbose in some cases, this offers a nicer experience for folks who use utility class-based CSS. ([#&#8203;7194](https://github.com/remix-run/react-router/issues/7194)) ```tsx // Before <NavLink className="link" activeClassName="active-link" /> <NavLink style={{ color: "blue" }} activeStyle={{ color: "green" }} /> // After <NavLink className={({ isActive }) => `link ${ isActive ? "active-link" : // Couldn't do this before! "inactive-link" }` } /> <NavLink style={({ isActive }) => ({ color: isActive ? "green" : "blue" })} /> ``` > **Note:** You can always abstract over this feature in a custom `NavLink` if you prefer the old v5 API. - The `useRoutes` API has changed slightly. Instead of passing a basename as the second argument, you should instead pass it as a named property in an object: ```tsx // Before useRoutes([...routes], basename); // After useRoutes([...routes], { basename }); ``` ##### 🐛 Bugfixes - The `basename` prop on `Routes` is treated as case-insensitive ([#&#8203;7997](https://github.com/remix-run/react-router/issues/7997)) - `useNavigate` previously used the incorrect `pathname` when called from parent routes when the URL matches one of its children. This fix also applies to `useSearchParams` ([#&#8203;7880](https://github.com/remix-run/react-router/issues/7880)) ##### ✨ Enhancements - `Routes` and `useRoutes` now allow you to override the `location`, which may be useful when building some modal interfaces and route transition animations. We are working hard to update our docs to include examples for advanced patterns where this might be useful, but in the mean time this also brings `Routes` closer to feature parity with v5's `Switch` via the `location` prop. ([#&#8203;7117](https://github.com/remix-run/react-router/issues/7117)) - Provided new hooks `useClickHandler` and `usePressHandler` to make customizing `Links` a bit easier. ([#&#8203;7998](https://github.com/remix-run/react-router/issues/7998)) - **Please note:** with great power comes great responsibility. If you create a custom `Link`, be sure to render an actual HTML anchor element, otherwise your app will likely be inaccessible without a significant amount of additional work which, I assure you, you don't want to do! ##### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ##### 🙏 Credits Thanks to [@&#8203;andrelandgraf](https://github.com/andrelandgraf), [@&#8203;dhulme](https://github.com/dhulme), [@&#8203;fgatti675](https://github.com/fgatti675), [@&#8203;hugmanrique](https://github.com/hugmanrique), [@&#8203;MeiKatz](https://github.com/MeiKatz), [@&#8203;chaance](https://github.com/chaance) and [@&#8203;mjackson](https://github.com/mjackson) for your contributions! ### [`v6.0.0-beta.2`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.2) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.1...v6.0.0-beta.2) ##### 🐛 Bugfixes - Fixed a bug that [broke paths in nested routes](https://github.com/remix-run/react-router/issues/7948) - Adds missing `displayName` back to `<Link />` and `<NavLink />` components ##### ✨ Enhancements - The `navigate` function now prepends hash and search strings by default: ```js navigate({ search: "?foo=1&bar=2" }); // this works as expected! navigate({ search: "foo=1&bar=2" }); // this also works! ``` - `useParams` now returns [parameters from nested `<Route />`s when called in a parent `<Route />`](https://github.com/remix-run/react-router/issues/7960) ##### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ##### 🙏 Credits Thanks to [@&#8203;liho98](https://github.com/liho98), [@&#8203;wojtekmaj](https://github.com/wojtekmaj), [@&#8203;cravend](https://github.com/cravend), [@&#8203;chaance](https://github.com/chaance) and [@&#8203;mjackson](https://github.com/mjackson) for your contributions! Enjoy! ### [`v6.0.0-beta.1`](https://github.com/remix-run/react-router/releases/tag/v6.0.0-beta.1) [Compare Source](https://github.com/remix-run/react-router/compare/v6.0.0-beta.0...v6.0.0-beta.1) We're on the road to a stable v6 release! There are no new features in this release since `beta.0`, but a handful of squashed bugs, perf enhancements, and DX improvements for TypeScript users. ##### 🐛 Bugfixes - Fixed a few bugs with pathname resolution. `+` characters no longer get decoded into spaces, and that little [`*` is just a little less greedy](https://github.com/remix-run/react-router/issues/7529) (e.g., `app/*` no longer matches `apples/*`). - `Link` and `navigate` should properly [respect the `basename` when using absolute paths](https://github.com/remix-run/react-router/issues/7216). ##### ✨ Enhancements - Internally we are separating `navigator` into a separate context object, meaning your components that call `useNavigate` will probably render a little less often. Wowza, much perf! - `react-router-dom` and `react-router-native` now re-exports all types exported from `react-router` ##### 💻 Installing Development for v6 is chugging along [on the `dev` branch](https://github.com/remix-run/react-router/tree/dev). If you'd like to test it out, install from npm: ```bash $ npm install history react-router-dom@next ``` ##### 🙏 Credits Thanks to [@&#8203;brookslybrand](https://github.com/brookslybrand), [@&#8203;bogdansoare](https://github.com/bogdansoare), [@&#8203;chaance](https://github.com/chaance) and [@&#8203;mjackson](https://github.com/mjackson) for your contributions! Enjoy! </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, 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:eyJjcmVhdGVkSW5WZXIiOiIzNC4xNjAuMCIsInVwZGF0ZWRJblZlciI6IjM0LjE2MC4wIn0=-->
kjuulh added 1 commit 2024-04-06 22:43:44 +02:00
kjuulh changed title from Update react-router monorepo to v6.22.3 to fix(deps): update react-router monorepo to v6.22.3 2024-04-07 00:27:31 +02:00
kjuulh force-pushed renovate/react-router-monorepo from dbd1e61d6f to d2ebbd8ee6 2024-04-07 00:27:32 +02:00 Compare
kjuulh force-pushed renovate/react-router-monorepo from d2ebbd8ee6 to 3e99380a07 2024-04-07 01:03:31 +02:00 Compare
kjuulh merged commit 3e99380a07 into main 2024-04-07 01:36:54 +02:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: kjuulh/backstage#3
No description provided.