# React Router Releases
This page lists all releases/release notes for React Router back to `v6.0.0`. For releases prior to v6, please refer to the [Github Releases Page](https://github.com/remix-run/react-router/releases).
We manage release notes in this file instead of the paginated Github Releases Page for 2 reasons:
- Pagination in the Github UI means that you cannot easily search release notes for a large span of releases at once
- The paginated Github interface also cuts off longer releases notes without indication in list view, and you need to click into the detail view to see the full set of release notes
Table of Contents
- [React Router Releases](#react-router-releases)
- [v7.0.0](#v700)
- [Breaking Changes](#breaking-changes)
- [Package Restructuring](#package-restructuring)
- [Removed Adapter Re-exports](#removed-adapter-re-exports)
- [Removed APIs](#removed-apis)
- [Minimum Versions](#minimum-versions)
- [Adopted Future Flag Behaviors](#adopted-future-flag-behaviors)
- [Vite Compiler](#vite-compiler)
- [Exposed Router Promises](#exposed-router-promises)
- [Other Notable Changes](#other-notable-changes)
- [`routes.ts`](#routests)
- [Typesafety improvements](#typesafety-improvements)
- [Setup](#setup)
- [`typegen` command](#typegen-command)
- [TypeScript plugin](#typescript-plugin)
- [VSCode](#vscode)
- [Troubleshooting](#troubleshooting)
- [Prerendering](#prerendering)
- [Major Changes (`react-router`)](#major-changes-react-router)
- [Major Changes (`@react-router/*`)](#major-changes-react-router-1)
- [Minor Changes](#minor-changes)
- [Patch Changes](#patch-changes)
- [Changes by Package](#changes-by-package)
- [**Full Changelog**: `v6.28.0...v7.0.0`](#full-changelog-v6280v700)
- [v6.28.0](#v6280)
- [What's Changed](#whats-changed)
- [Minor Changes](#minor-changes-1)
- [Patch Changes](#patch-changes-1)
- [v6.27.0](#v6270)
- [What's Changed](#whats-changed-1)
- [Stabilized APIs](#stabilized-apis)
- [Minor Changes](#minor-changes-2)
- [Patch Changes](#patch-changes-2)
- [v6.26.2](#v6262)
- [Patch Changes](#patch-changes-3)
- [v6.26.1](#v6261)
- [Patch Changes](#patch-changes-4)
- [v6.26.0](#v6260)
- [Minor Changes](#minor-changes-3)
- [Patch Changes](#patch-changes-5)
- [v6.25.1](#v6251)
- [Patch Changes](#patch-changes-6)
- [v6.25.0](#v6250)
- [What's Changed](#whats-changed-2)
- [Stabilized `v7_skipActionErrorRevalidation`](#stabilized-v7_skipactionerrorrevalidation)
- [Minor Changes](#minor-changes-4)
- [Patch Changes](#patch-changes-7)
- [v6.24.1](#v6241)
- [Patch Changes](#patch-changes-8)
- [v6.24.0](#v6240)
- [What's Changed](#whats-changed-3)
- [Lazy Route Discovery (a.k.a. "Fog of War")](#lazy-route-discovery-aka-fog-of-war)
- [Minor Changes](#minor-changes-5)
- [Patch Changes](#patch-changes-9)
- [v6.23.1](#v6231)
- [Patch Changes](#patch-changes-10)
- [v6.23.0](#v6230)
- [What's Changed](#whats-changed-4)
- [Data Strategy (unstable)](#data-strategy-unstable)
- [Skip Action Error Revalidation (unstable)](#skip-action-error-revalidation-unstable)
- [Minor Changes](#minor-changes-6)
- [v6.22.3](#v6223)
- [Patch Changes](#patch-changes-11)
- [v6.22.2](#v6222)
- [Patch Changes](#patch-changes-12)
- [v6.22.1](#v6221)
- [Patch Changes](#patch-changes-13)
- [v6.22.0](#v6220)
- [What's Changed](#whats-changed-5)
- [Core Web Vitals Technology Report Flag](#core-web-vitals-technology-report-flag)
- [Minor Changes](#minor-changes-7)
- [Patch Changes](#patch-changes-14)
- [v6.21.3](#v6213)
- [Patch Changes](#patch-changes-15)
- [v6.21.2](#v6212)
- [Patch Changes](#patch-changes-16)
- [v6.21.1](#v6211)
- [Patch Changes](#patch-changes-17)
- [v6.21.0](#v6210)
- [What's Changed](#whats-changed-6)
- [`future.v7_relativeSplatPath`](#futurev7_relativesplatpath)
- [Partial Hydration](#partial-hydration)
- [Minor Changes](#minor-changes-8)
- [Patch Changes](#patch-changes-18)
- [v6.20.1](#v6201)
- [Patch Changes](#patch-changes-19)
- [v6.20.0](#v6200)
- [Minor Changes](#minor-changes-9)
- [Patch Changes](#patch-changes-20)
- [v6.19.0](#v6190)
- [What's Changed](#whats-changed-7)
- [`unstable_flushSync` API](#unstable_flushsync-api)
- [Minor Changes](#minor-changes-10)
- [Patch Changes](#patch-changes-21)
- [v6.18.0](#v6180)
- [What's Changed](#whats-changed-8)
- [New Fetcher APIs](#new-fetcher-apis)
- [Persistence Future Flag (`future.v7_fetcherPersist`)](#persistence-future-flag-futurev7_fetcherpersist)
- [Minor Changes](#minor-changes-11)
- [Patch Changes](#patch-changes-22)
- [v6.17.0](#v6170)
- [What's Changed](#whats-changed-9)
- [View Transitions π](#view-transitions-)
- [Minor Changes](#minor-changes-12)
- [Patch Changes](#patch-changes-23)
- [v6.16.0](#v6160)
- [Minor Changes](#minor-changes-13)
- [Patch Changes](#patch-changes-24)
- [v6.15.0](#v6150)
- [Minor Changes](#minor-changes-14)
- [Patch Changes](#patch-changes-25)
- [v6.14.2](#v6142)
- [Patch Changes](#patch-changes-26)
- [v6.14.1](#v6141)
- [Patch Changes](#patch-changes-27)
- [v6.14.0](#v6140)
- [What's Changed](#whats-changed-10)
- [JSON/Text Submissions](#jsontext-submissions)
- [Minor Changes](#minor-changes-15)
- [Patch Changes](#patch-changes-28)
- [v6.13.0](#v6130)
- [What's Changed](#whats-changed-11)
- [`future.v7_startTransition`](#futurev7_starttransition)
- [Minor Changes](#minor-changes-16)
- [Patch Changes](#patch-changes-29)
- [v6.12.1](#v6121)
- [Patch Changes](#patch-changes-30)
- [v6.12.0](#v6120)
- [What's Changed](#whats-changed-12)
- [`React.startTransition` support](#reactstarttransition-support)
- [Minor Changes](#minor-changes-17)
- [Patch Changes](#patch-changes-31)
- [v6.11.2](#v6112)
- [Patch Changes](#patch-changes-32)
- [v6.11.1](#v6111)
- [Patch Changes](#patch-changes-33)
- [v6.11.0](#v6110)
- [Minor Changes](#minor-changes-18)
- [Patch Changes](#patch-changes-34)
- [v6.10.0](#v6100)
- [What's Changed](#whats-changed-13)
- [Minor Changes](#minor-changes-19)
- [`future.v7_normalizeFormMethod`](#futurev7_normalizeformmethod)
- [Patch Changes](#patch-changes-35)
- [v6.9.0](#v690)
- [What's Changed](#whats-changed-14)
- [`Component`/`ErrorBoundary` route properties](#componenterrorboundary-route-properties)
- [Introducing Lazy Route Modules](#introducing-lazy-route-modules)
- [Minor Changes](#minor-changes-20)
- [Patch Changes](#patch-changes-36)
- [v6.8.2](#v682)
- [Patch Changes](#patch-changes-37)
- [v6.8.1](#v681)
- [Patch Changes](#patch-changes-38)
- [v6.8.0](#v680)
- [Minor Changes](#minor-changes-21)
- [Patch Changes](#patch-changes-39)
- [v6.7.0](#v670)
- [Minor Changes](#minor-changes-22)
- [Patch Changes](#patch-changes-40)
- [v6.6.2](#v662)
- [Patch Changes](#patch-changes-41)
- [v6.6.1](#v661)
- [Patch Changes](#patch-changes-42)
- [v6.6.0](#v660)
- [What's Changed](#whats-changed-15)
- [Minor Changes](#minor-changes-23)
- [Patch Changes](#patch-changes-43)
- [v6.5.0](#v650)
- [What's Changed](#whats-changed-16)
- [Minor Changes](#minor-changes-24)
- [Patch Changes](#patch-changes-44)
- [v6.4.5](#v645)
- [Patch Changes](#patch-changes-45)
- [v6.4.4](#v644)
- [Patch Changes](#patch-changes-46)
- [v6.4.3](#v643)
- [Patch Changes](#patch-changes-47)
- [v6.4.2](#v642)
- [Patch Changes](#patch-changes-48)
- [v6.4.1](#v641)
- [Patch Changes](#patch-changes-49)
- [v6.4.0](#v640)
- [What's Changed](#whats-changed-17)
- [Remix Data APIs](#remix-data-apis)
- [Patch Changes](#patch-changes-50)
- [v6.3.0](#v630)
- [Minor Changes](#minor-changes-25)
- [v6.2.2](#v622)
- [Patch Changes](#patch-changes-51)
- [v6.2.1](#v621)
- [Patch Changes](#patch-changes-52)
- [v6.2.0](#v620)
- [Minor Changes](#minor-changes-26)
- [Patch Changes](#patch-changes-53)
- [v6.1.1](#v611)
- [Patch Changes](#patch-changes-54)
- [v6.1.0](#v610)
- [Minor Changes](#minor-changes-27)
- [Patch Changes](#patch-changes-55)
- [v6.0.2](#v602)
- [Patch Changes](#patch-changes-56)
- [v6.0.1](#v601)
- [Patch Changes](#patch-changes-57)
- [v6.0.0](#v600)
## v7.0.0
Date: 2024-11-21
### Breaking Changes
#### Package Restructuring
- The `react-router-dom`, `@remix-run/react`, `@remix-run/server-runtime`, and `@remix-run/router` have been collapsed into the `react-router` package
- To ease migration, `react-router-dom` is still published in v7 as a re-export of everything from `react-router`
- The `@remix-run/cloudflare-pages` and `@remix-run/cloudflare-workers` have been collapsed into `@react-router/cloudflare` package`
- The `react-router-dom-v5-compat` and `react-router-native` packages are removed starting with v7
#### Removed Adapter Re-exports
Remix v2 used to re-export all common `@remix-run/server-runtime` APIs through the various runtime packages (`node`, `cloudflare`, `deno`) so that you wouldn't need an additional `@remix-run/server-runtime` dependency in your `package.json`. With the collapsing of packages into `react-router`, these common APIs are now no longer re-exported through the runtime adapters. You should import all common APIs from `react-router`, and only import runtime-specific APIs from the runtime packages:
```jsx
// Runtime-specific APIs
import { createFileSessionStorage } from "@react-router/node";
// Runtime-agnostic APIs
import { redirect, useLoaderData } from "react-router";
```
#### Removed APIs
The following APIs have been removed in React Router v7:
- `json`
- `defer`
- `unstable_composeUploadHandlers`
- `unstable_createMemoryUploadHandler`
- `unstable_parseMultipartFormData`
#### Minimum Versions
React Router v7 requires the following minimum versions:
- `node@20`
- React Router no longer provides an `installGlobals` method to [polyfill](https://reactrouter.com/dev/guides/deploying/custom-node#polyfilling-fetch) the `fetch` API
- `react@18`, `react-dom@18`
#### Adopted Future Flag Behaviors
Remix and React Router follow an [API Development Strategy](https://reactrouter.com/en/main/guides/api-development-strategy) leveraging "Future Flags" to avoid introducing a slew of breaking changes in a major release. Instead, breaking changes are introduce din minor releases behind a flag, allowing users to opt-in at their convenience. In the next major release, all future flag behaviors become the default behavior.
The following previously flagged behaviors are now the default in React Router v7:
- [React Router v6 flags](https://reactrouter.com/en/v6/upgrading/future)
- `future.v7_relativeSplatPath`
- `future.v7_startTransition`
- `future.v7_fetcherPersist`
- `future.v7_normalizeFormMethod`
- `future.v7_partialHydration`
- `future.v7_skipActionStatusRevalidation`
- [Remix v2 flags](https://remix.run/docs/en/v2/start/future-flags)
- `future.v3_fetcherPersist`
- `future.v3_relativeSplatPath`
- `future.v3_throwAbortReason`
- `future.v3_singleFetch`
- `future.v3_lazyRouteDiscovery`
- `future.v3_optimizeDeps`
#### Vite Compiler
The [Remix Vite plugin](https://remix.run/docs/en/2.12.1/start/future-flags#vite-plugin) is the proper way to build full-stack SSR apps using React Router v7. The former `esbuild`-based compiler is no longer available.
**Renamed `vitePlugin` and `cloudflareDevProxyVitePlugin`**
For Remix consumers migrating to React Router, the `vitePlugin` and `cloudflareDevProxyVitePlugin` exports have been renamed and moved ([#11904](https://github.com/remix-run/react-router/pull/11904))
```diff
-import {
- vitePlugin as remix,
- cloudflareDevProxyVitePlugin,
-} from "@remix/dev";
+import { reactRouter } from "@react-router/dev/vite";
+import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare";
```
**Removed Vite Plugin `manifest` option**
For Remix consumers migrating to React Router, the Vite plugin's `manifest` option has been removed. The `manifest` option been superseded by the more powerful `buildEnd` hook since it's passed the `buildManifest` argument. You can still write the build manifest to disk if needed, but you'll most likely find it more convenient to write any logic depending on the build manifest within the `buildEnd` hook itself. ([#11573](https://github.com/remix-run/react-router/pull/11573))
If you were using the `manifest` option, you can replace it with a `buildEnd` hook that writes the manifest to disk like this:
```js
import { reactRouter } from "@react-router/dev/vite";
import { writeFile } from "node:fs/promises";
export default {
plugins: [
reactRouter({
async buildEnd({ buildManifest }) {
await writeFile(
"build/manifest.json",
JSON.stringify(buildManifest, null, 2),
"utf-8"
);
},
}),
],
};
```
#### Exposed Router Promises
Because React 19 will have first-class support for handling promises in the render pass (via `React.use` and `useAction`), we are now comfortable exposing the promises for the APIs that previously returned `undefined`:
- `useNavigate()`
- `useSubmit()`
- `useFetcher().load`
- `useFetcher().submit`
- `useRevalidator().revalidate()`
### Other Notable Changes
#### `routes.ts`
When using the React Router Vite plugin, routes are defined in `app/routes.ts`. Route config is exported via the `routes` export, conforming to the `RouteConfig` type. Route helper functions `route`, `index`, and `layout` are provided to make declarative type-safe route definitions easier.
```ts
// app/routes.ts
import {
type RouteConfig,
route,
index,
layout,
} from "@react-router/dev/routes";
export const routes: RouteConfig = [
index("./home.tsx"),
route("about", "./about.tsx"),
layout("./auth/layout.tsx", [
route("login", "./auth/login.tsx"),
route("register", "./auth/register.tsx"),
]),
route("concerts", [
index("./concerts/home.tsx"),
route(":city", "./concerts/city.tsx"),
route("trending", "./concerts/trending.tsx"),
]),
];
```
For Remix consumers migrating to React Router, you can still configure file system routing within `routes.ts` using the `@react-router/fs-routes` package. A minimal route config that reproduces the default Remix setup looks like this:
```ts
// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export const routes: RouteConfig = flatRoutes();
```
If you want to migrate from file system routing to config-based routes, you can mix and match approaches by spreading the results of the async `flatRoutes` function into the array of config-based routes.
```ts
// app/routes.ts
import { type RouteConfig, route } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export const routes: RouteConfig = [
// Example config-based route:
route("/hello", "./routes/hello.tsx"),
// File system routes scoped to a different directory:
...(await flatRoutes({
rootDirectory: "fs-routes",
})),
];
```
If you were using Remix's `routes` option to use alternative file system routing conventions, you can adapt these to the new `RouteConfig` format using `@react-router/remix-config-routes-adapter`.
For example, if you were using [Remix v1 route conventions](https://remix.run/docs/en/1.19.3/file-conventions/routes-files) in Remix v2, you can combine `@react-router/remix-config-routes-adapter` with `@remix-run/v1-route-convention` to adapt this to React Router:
```ts
// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { remixConfigRoutes } from "@react-router/remix-config-routes-adapter";
import { createRoutesFromFolders } from "@remix-run/v1-route-convention";
export const routes: RouteConfig = remixConfigRoutes(async (defineRoutes) => {
return createRoutesFromFolders(defineRoutes, {
ignoredFilePatterns: ["**/.*", "**/*.css"],
});
});
```
Also note that, if you were using Remix's `routes` option to define config-based routes, you can also adapt these to the new `RouteConfig` format using `@react-router/remix-config-routes-adapter` with minimal code changes. While this makes for a fast migration path, we recommend migrating any config-based routes from Remix to the new `RouteConfig` format since it's a fairly straightforward migration.
```diff
// app/routes.ts
-import { type RouteConfig } from "@react-router/dev/routes";
+import { type RouteConfig, route } from "@react-router/dev/routes";
-import { remixConfigRoutes } from "@react-router/remix-config-routes-adapter";
-export const routes: RouteConfig = remixConfigRoutes(async (defineRoutes) => {
- defineRoutes((route) => {
- route("/parent", "./routes/parent.tsx", () => [
- route("/child", "./routes/child.tsx"),
- ]);
- });
-});
+export const routes: RouteConfig = [
+ route("/parent", "./routes/parent.tsx", [
+ route("/child", "./routes/child.tsx"),
+ ]),
+];
```
#### Typesafety improvements
React Router now generates types for each of your route modules and passes typed props to route module component exports ([#11961](https://github.com/remix-run/react-router/pull/11961), [#12019](https://github.com/remix-run/react-router/pull/12019)). You can access those types by importing them from `./+types.`.
For example:
```ts
// app/routes/product.tsx
import type * as Route from "./+types.product";
export function loader({ params }: Route.LoaderArgs) {}
export default function Component({ loaderData }: Route.ComponentProps) {}
```
This initial implementation targets type inference for:
- `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
- `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
- `ActionData` : Action data from `action` and/or `clientAction` within your route module
These types are then used to create types for route export args and props:
- `LoaderArgs`
- `ClientLoaderArgs`
- `ActionArgs`
- `ClientActionArgs`
- `HydrateFallbackProps`
- `ComponentProps` (for the `default` export)
- `ErrorBoundaryProps`
In the future, we plan to add types for the rest of the route module exports: `meta`, `links`, `headers`, `shouldRevalidate`, etc.
We also plan to generate types for typesafe `Link`s:
```tsx
// ^^^^^^^^^^^^^ ^^^^^^^^^
// typesafe `to` and `params` based on the available routes in your app
```
##### Setup
React Router will generate types into a `.react-router/` directory at the root of your app. This directory is fully managed by React Router and is derived based on your route config (`routes.ts`).
π **Add `.react-router/` to `.gitignore`**
```txt
.react-router
```
You should also ensure that generated types for routes are always present before running typechecking, especially for running typechecking in CI.
π **Add `react-router typegen` to your `typecheck` command in `package.json`**
```json
{
"scripts": {
"typecheck": "react-router typegen && tsc"
}
}
```
To get TypeScript to use those generated types, you'll need to add them to `include` in `tsconfig.json`. And to be able to import them as if they files next to your route modules, you'll also need to configure `rootDirs`.
π **Configure `tsconfig.json` for generated types**
```json
{
"include": [".react-router/types/**/*"],
"compilerOptions": {
"rootDirs": [".", "./.react-router/types"]
}
}
```
##### `typegen` command
You can manually generate types with the new `typegen` command:
```sh
react-router typegen
```
However, manual type generation is tedious and types can get out of sync quickly if you ever forget to run `typegen`. Instead, we recommend that you setup our new TypeScript plugin which will automatically generate fresh types whenever routes change. That way, you'll always have up-to-date types.
##### TypeScript plugin
To get automatic type generation, you can use our new TypeScript plugin.
π **Add the TypeScript plugin to `tsconfig.json`**
```json
{
"compilerOptions": {
"plugins": [{ "name": "@react-router/dev" }]
}
}
```
We plan to add some other goodies to our TypeScript plugin soon, including:
- Automatic `jsdoc` for route exports that include links to official docs
- Autocomplete for route exports
- Warnings for non-HMR compliant exports
###### VSCode
TypeScript looks for plugins registered in `tsconfig.json` in the local `node_modules/`,
but VSCode ships with its own copy of TypeScript that is installed outside of your project.
For TypeScript plugins to work, you'll need to tell VSCode to use the local workspace version of TypeScript.
π **Ensure that VSCode is using the workspace version of TypeScript**
This should already be set up for you by a `.vscode/settings.json`:
```json
{
"typescript.tsdk": "node_modules/typescript/lib"
}
```
Alternatively, you can open up any TypeScript file and use CMD+SHIFT+P to find `Select TypeScript Version` and then select `Use Workspace Version`. You may need to quit VSCode and reopen it for this setting to take effect.
###### Troubleshooting
In VSCode, open up any TypeScript file in your project and then use CMD+SHIFT+P to select `Open TS Server log`. There should be a log for `[react-router] setup` that indicates that the plugin was resolved correctly. Then look for any errors in the log.
#### Prerendering
React Router v7 includes a new `prerender` config in the vite plugin to support SSG use-cases. This will pre-render your `.html` and `.data` files at build time and so you can serve them statically at runtime from a running server or a CDN ([#11539](https://github.com/remix-run/react-router/pull/11539))
```ts
export default defineConfig({
plugins: [
reactRouter({
async prerender({ getStaticPaths }) {
let slugs = await fakeGetSlugsFromCms();
return [
...getStaticPaths(),
...slugs.map((slug) => `/product/${slug}`),
];
},
}),
tsconfigPaths(),
],
});
async function fakeGetSlugsFromCms() {
await new Promise((r) => setTimeout(r, 1000));
return ["shirt", "hat"];
}
```
### Major Changes (`react-router`)
- Remove the original `defer` implementation in favor of using raw promises via single fetch and `turbo-stream` ([#11744](https://github.com/remix-run/react-router/pull/11744))
- This removes these exports from React Router:
- `defer`
- `AbortedDeferredError`
- `type TypedDeferredData`
- `UNSAFE_DeferredData`
- `UNSAFE_DEFERRED_SYMBOL`
- Collapse packages into `react-router`([#11505](https://github.com/remix-run/react-router/pull/11505))
- `@remix-run/router`
- `react-router-dom`
- `@remix-run/server-runtime`
- `@remix-run/testing`
- As a note, the `react-router-dom` package is maintained to ease adoption but it simply re-exports all APIs from `react-router`
- Drop support for Node 16, React Router SSR now requires Node 18 or higher ([#11391](https://github.com/remix-run/react-router/pull/11391), [#11690](https://github.com/remix-run/react-router/pull/11690))
- Remove `future.v7_startTransition` flag ([#11696](https://github.com/remix-run/react-router/pull/11696))
- Expose the underlying router promises from the following APIs for composition in React 19 APIs: ([#11521](https://github.com/remix-run/react-router/pull/11521))
- Remove `future.v7_normalizeFormMethod` future flag ([#11697](https://github.com/remix-run/react-router/pull/11697))
- Imports/Exports cleanup ([#11840](https://github.com/remix-run/react-router/pull/11840))
- Removed the following exports that were previously public API from `@remix-run/router`
- types
- `AgnosticDataIndexRouteObject`
- `AgnosticDataNonIndexRouteObject`
- `AgnosticDataRouteMatch`
- `AgnosticDataRouteObject`
- `AgnosticIndexRouteObject`
- `AgnosticNonIndexRouteObject`
- `AgnosticRouteMatch`
- `AgnosticRouteObject`
- `TrackedPromise`
- `unstable_AgnosticPatchRoutesOnMissFunction`
- `Action` -> exported as `NavigationType` via `react-router`
- `Router` exported as `RemixRouter` to differentiate from RR's ``
- API
- `getToPathname` (`@private`)
- `joinPaths` (`@private`)
- `normalizePathname` (`@private`)
- `resolveTo` (`@private`)
- `stripBasename` (`@private`)
- `createBrowserHistory` -> in favor of `createBrowserRouter`
- `createHashHistory` -> in favor of `createHashRouter`
- `createMemoryHistory` -> in favor of `createMemoryRouter`
- `createRouter`
- `createStaticHandler` -> in favor of wrapper `createStaticHandler` in RR Dom
- `getStaticContextFromError`
- Removed the following exports that were previously public API from `react-router`
- `Hash`
- `Pathname`
- `Search`
- Remove `future.v7_prependBasename` from the internalized `@remix-run/router` package ([#11726](https://github.com/remix-run/react-router/pull/11726))
- Remove `future.v7_throwAbortReason` from internalized `@remix-run/router` package ([#11728](https://github.com/remix-run/react-router/pull/11728))
- Add `exports` field to all packages ([#11675](https://github.com/remix-run/react-router/pull/11675))
- Renamed `RemixContext` to `FrameworkContext` ([#11705](https://github.com/remix-run/react-router/pull/11705))
- Update the minimum React version to 18 ([#11689](https://github.com/remix-run/react-router/pull/11689))
- `PrefetchPageDescriptor` replaced by `PageLinkDescriptor` ([#11960](https://github.com/remix-run/react-router/pull/11960))
- Remove the `future.v7_partialHydration` flag ([#11725](https://github.com/remix-run/react-router/pull/11725))
- This also removes the `` prop
- To migrate, move the `fallbackElement` to a `hydrateFallbackElement`/`HydrateFallback` on your root route
- Also worth nothing there is a related breaking changer with this future flag:
- Without `future.v7_partialHydration` (when using `fallbackElement`), `state.navigation` was populated during the initial load
- With `future.v7_partialHydration`, `state.navigation` remains in an `"idle"` state during the initial load
- Remove `future.v7_relativeSplatPath` future flag ([#11695](https://github.com/remix-run/react-router/pull/11695))
- Remove remaining future flags ([#11820](https://github.com/remix-run/react-router/pull/11820))
- React Router `v7_skipActionErrorRevalidation`
- Remix `v3_fetcherPersist`, `v3_relativeSplatPath`, `v3_throwAbortReason`
- Rename `createRemixStub` to `createRoutesStub` ([#11692](https://github.com/remix-run/react-router/pull/11692))
- Remove `@remix-run/router` deprecated `detectErrorBoundary` option in favor of `mapRouteProperties` ([#11751](https://github.com/remix-run/react-router/pull/11751))
- Add `react-router/dom` subpath export to properly enable `react-dom` as an optional `peerDependency` ([#11851](https://github.com/remix-run/react-router/pull/11851))
- This ensures that we don't blindly `import ReactDOM from "react-dom"` in `` in order to access `ReactDOM.flushSync()`, since that would break `createMemoryRouter` use cases in non-DOM environments
- DOM environments should import from `react-router/dom` to get the proper component that makes `ReactDOM.flushSync()` available:
- If you are using the Vite plugin, use this in your `entry.client.tsx`:
- `import { HydratedRouter } from 'react-router/dom'`
- If you are not using the Vite plugin and are manually calling `createBrowserRouter`/`createHashRouter`:
- `import { RouterProvider } from "react-router/dom"`
- Remove `future.v7_fetcherPersist` flag ([#11731](https://github.com/remix-run/react-router/pull/11731))
- Allow returning `undefined` from loaders and actions ([#11680](https://github.com/remix-run/react-router/pull/11680), [#12057]([https://github.com/remix-run/react-router/pull/1205))
- Use `createRemixRouter`/`RouterProvider` in `entry.client` instead of `RemixBrowser` ([#11469](https://github.com/remix-run/react-router/pull/11469))
- Remove the deprecated `json` utility ([#12146](https://github.com/remix-run/react-router/pull/12146))
- You can use [`Response.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static) if you still need to construct JSON responses in your app
### Major Changes (`@react-router/*`)
- Remove `future.v3_singleFetch` flag ([#11522](https://github.com/remix-run/react-router/pull/11522))
- Drop support for Node 16 and 18, update minimum Node version to 20 ([#11690](https://github.com/remix-run/react-router/pull/11690), [#12171](https://github.com/remix-run/react-router/pull/12171))
- Remove `installGlobals()` as this should no longer be necessary
- Add `exports` field to all packages ([#11675](https://github.com/remix-run/react-router/pull/11675))
- No longer re-export APIs from `react-router` through different runtime/adapter packages ([#11702](https://github.com/remix-run/react-router/pull/11702))
- For Remix consumers migrating to React Router, the `crypto` global from the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is now required when using cookie and session APIs
- This means that the following APIs are provided from `react-router` rather than platform-specific packages: ([#11837](https://github.com/remix-run/react-router/pull/11837))
- `createCookie`
- `createCookieSessionStorage`
- `createMemorySessionStorage`
- `createSessionStorage`
- For consumers running older versions of Node, the `installGlobals` function from `@remix-run/node` has been updated to define `globalThis.crypto`, using [Node's `require('node:crypto').webcrypto` implementation](https://nodejs.org/api/webcrypto.html)
- Since platform-specific packages no longer need to implement this API, the following low-level APIs have been removed:
- `createCookieFactory`
- `createSessionStorageFactory`
- `createCookieSessionStorageFactory`
- `createMemorySessionStorageFactory`
- Consolidate types previously duplicated across `@remix-run/router`, `@remix-run/server-runtime`, and `@remix-run/react` now that they all live in `react-router` ([#12177](https://github.com/remix-run/react-router/pull/12177))
- Examples: `LoaderFunction`, `LoaderFunctionArgs`, `ActionFunction`, `ActionFunctionArgs`, `DataFunctionArgs`, `RouteManifest`, `LinksFunction`, `Route`, `EntryRoute`
- The `RouteManifest` type used by the "remix" code is now slightly stricter because it is using the former `@remix-run/router` `RouteManifest`
- `Record -> Record`
- Removed `AppData` type in favor of inlining `unknown` in the few locations it was used
- Removed `ServerRuntimeMeta*` types in favor of the `Meta*` types they were duplicated from
- Migrate Remix v2 type generics to React Router ([#12180](https://github.com/remix-run/react-router/pull/12180))
- These generics are provided for Remix v2 migration purposes
- These generics and the APIs they exist on should be considered informally deprecated in favor of the new `Route.*` types
- Anyone migrating from React Router v6 should probably not leverage these new generics and should migrate straight to the `Route.*` types
- For React Router v6 users, these generics are new and should not impact your app, with one exception
- `useFetcher` previously had an optional generic (used primarily by Remix v2) that expected the data type
- This has been updated in v7 to expect the type of the function that generates the data (i.e., `typeof loader`/`typeof action`)
- Therefore, you should update your usages:
- β `useFetcher()`
- β `useFetcher()`
- Update `cookie` dependency to `^1.0.1` - please see the [release notes](https://github.com/jshttp/cookie/releases) for any breaking changes ([#12172](https://github.com/remix-run/react-router/pull/12172))
- `@react-router/cloudflare` - For Remix consumers migrating to React Router, all exports from `@remix-run/cloudflare-pages` are now provided for React Router consumers in the `@react-router/cloudflare` package. There is no longer a separate package for Cloudflare Pages. ([#11801](https://github.com/remix-run/react-router/pull/11801))
- `@react-router/cloudflare` - The `@remix-run/cloudflare-workers` package has been deprecated. Remix consumers migrating to React Router should use the `@react-router/cloudflare` package directly. For guidance on how to use `@react-router/cloudflare` within a Cloudflare Workers context, refer to the Cloudflare Workers template. ([#11801](https://github.com/remix-run/react-router/pull/11801))
- `@react-router/dev` - For Remix consumers migrating to React Router, the `vitePlugin` and `cloudflareDevProxyVitePlugin` exports have been renamed and moved. ([#11904](https://github.com/remix-run/react-router/pull/11904))
- `@react-router/dev` - For Remix consumers migrating to React Router who used the Vite plugin's `buildEnd` hook, the resolved `reactRouterConfig` object no longer contains a `publicPath` property since this belongs to Vite, not React Router ([#11575](https://github.com/remix-run/react-router/pull/11575))
- `@react-router/dev` - For Remix consumers migrating to React Router, the Vite plugin's `manifest` option has been removed ([#11573](https://github.com/remix-run/react-router/pull/11573))
- `@react-router/dev` - Update default `isbot` version to v5 and drop support for `isbot@3` ([#11770](https://github.com/remix-run/react-router/pull/11770))
- If you have `isbot@4` or `isbot@5` in your `package.json`:
- You do not need to make any changes
- If you have `isbot@3` in your `package.json` and you have your own `entry.server.tsx` file in your repo
- You do not need to make any changes
- You can upgrade to `isbot@5` independent of the React Router v7 upgrade
- If you have `isbot@3` in your `package.json` and you do not have your own `entry.server.tsx` file in your repo
- You are using the internal default entry provided by React Router v7 and you will need to upgrade to `isbot@5` in your `package.json`
- `@react-router/dev` - For Remix consumers migrating to React Router, Vite manifests (i.e. `.vite/manifest.json`) are now written within each build subdirectory, e.g. `build/client/.vite/manifest.json` and `build/server/.vite/manifest.json` instead of `build/.vite/client-manifest.json` and `build/.vite/server-manifest.json`. This means that the build output is now much closer to what you'd expect from a typical Vite project. ([#11573](https://github.com/remix-run/react-router/pull/11573))
- Originally the Remix Vite plugin moved all Vite manifests to a root-level `build/.vite` directory to avoid accidentally serving them in production, particularly from the client build. This was later improved with additional logic that deleted these Vite manifest files at the end of the build process unless Vite's `build.manifest` had been enabled within the app's Vite config. This greatly reduced the risk of accidentally serving the Vite manifests in production since they're only present when explicitly asked for. As a result, we can now assume that consumers will know that they need to manage these additional files themselves, and React Router can safely generate a more standard Vite build output.
### Minor Changes
- `react-router` - Params, loader data, and action data as props for route component exports ([#11961](https://github.com/remix-run/react-router/pull/11961))
- `react-router` - Add route module type generation ([#12019](https://github.com/remix-run/react-router/pull/12019))
- `react-router` - Remove duplicate `RouterProvider` implementations ([#11679](https://github.com/remix-run/react-router/pull/11679))
- `react-router` - Stabilize `unstable_dataStrategy` ([#11969](https://github.com/remix-run/react-router/pull/11969))
- `react-router` - Stabilize `unstable_patchRoutesOnNavigation` ([#11970](https://github.com/remix-run/react-router/pull/11970))
- `react-router` - Add prefetching support to `Link`/`NavLink` when using Remix SSR ([#11402](https://github.com/remix-run/react-router/pull/11402))
- `react-router` - Enhance `ScrollRestoration` so it can restore properly on an SSR'd document load ([#11401](https://github.com/remix-run/react-router/pull/11401))
- `@react-router/dev` - Add support for the `prerender` config in the React Router vite plugin, to support existing SSG use-cases ([#11539](https://github.com/remix-run/react-router/pull/11539))
- `@react-router/dev` - Remove internal `entry.server.spa.tsx` implementation which was not compatible with the Single Fetch async hydration approach ([#11681](https://github.com/remix-run/react-router/pull/11681))
- `@react-router/serve`: Update `express.static` configurations to support new `prerender` API ([#11547](https://github.com/remix-run/react-router/pull/11547))
- Assets in the `build/client/assets` folder are served as before, with a 1-year immutable `Cache-Control` header
- Static files outside of assets, such as pre-rendered `.html` and `.data` files are not served with a specific `Cache-Control` header
- `.data` files are served with `Content-Type: text/x-turbo`
- For some reason, when adding this via `express.static`, it seems to also add a `Cache-Control: public, max-age=0` to `.data` files
### Patch Changes
- Replace `substr` with `substring` ([#12080](https://github.com/remix-run/react-router/pull/12080))
- `react-router` - Fix redirects returned from loaders/actions using `data()` ([#12021](https://github.com/remix-run/react-router/pull/12021))
- `@react-router/dev` - Enable prerendering for resource routes ([#12200](https://github.com/remix-run/react-router/pull/12200))
- `@react-router/dev` - resolve config directory relative to flat output file structure ([#12187](https://github.com/remix-run/react-router/pull/12187))
### Changes by Package
- [`react-router`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router/CHANGELOG.md#700)
- [`@react-router/architect`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-architect/CHANGELOG.md#700)
- [`@react-router/cloudflare`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-cloudflare/CHANGELOG.md#700)
- [`@react-router/dev`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-dev/CHANGELOG.md#700)
- [`@react-router/express`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-express/CHANGELOG.md#700)
- [`@react-router/fs-routes`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-fs-routes/CHANGELOG.md#700)
- [`@react-router/node`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-node/CHANGELOG.md#700)
- [`@react-router/remix-config-routes-adapter`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-remix-config-routes-adapter/CHANGELOG.md#700)
- [`@react-router/serve`](https://github.com/remix-run/react-router/blob/react-router%407.0.0/packages/react-router-serve/CHANGELOG.md#700)
# **Full Changelog**: [`v6.28.0...v7.0.0`](https://github.com/remix-run/react-router/compare/react-router@6.28.0...react-router@7.0.0)
## v6.28.0
Date: 2024-11-06
### What's Changed
- In preparation for v7 we've added deprecation warnings for any future flags that you have not yet opted into. Please use the flags to better prepare for eventually upgrading to v7.
### Minor Changes
- Log deprecation warnings for v7 flags ([#11750](https://github.com/remix-run/react-router/pull/11750))
- Add deprecation warnings to `json`/`defer` in favor of returning raw objects
- These methods will be removed in React Router v7
### Patch Changes
- Update JSDoc URLs for new website structure (add /v6/ segment) ([#12141](https://github.com/remix-run/react-router/pull/12141))
**Full Changelog**: [`v6.27.0...v6.28.0`](https://github.com/remix-run/react-router/compare/react-router@6.27.0...react-router@6.28.0)
> > > > > > > dev
## v6.27.0
Date: 2024-10-11
### What's Changed
#### Stabilized APIs
This release stabilizes a handful of "unstable" APIs in preparation for the [pending](https://x.com/remix_run/status/1841926034868077009) React Router v7 release (see [these](https://remix.run/blog/merging-remix-and-react-router) [posts](https://remix.run/blog/incremental-path-to-react-19) for more info):
- `unstable_dataStrategy` β `dataStrategy` (`createBrowserRouter` and friends) ([Docs](https://reactrouter.com/v6/routers/create-browser-router#optsdatastrategy))
- `unstable_patchRoutesOnNavigation` β `patchRoutesOnNavigation` (`createBrowserRouter` and friends) ([Docs](https://reactrouter.com/v6/routers/create-browser-router#optspatchroutesonnavigation))
- `unstable_flushSync` β `flushSync` (`useSubmit`, `fetcher.load`, `fetcher.submit`) ([Docs](https://reactrouter.com/v6/hooks/use-submit#optionsflushsync))
- `unstable_viewTransition` β `viewTransition` (``, `;
function Component() {
return (
<>
{/* This is now correctly relative to /a/b, not /a/b/c */}
>
);
}
```
**Full Changelog**: [`6.18.0...6.19.0`](https://github.com/remix-run/react-router/compare/react-router@6.18.0...react-router@6.19.0)
## v6.18.0
Date: 2023-10-31
### What's Changed
#### New Fetcher APIs
Per this [RFC](https://github.com/remix-run/remix/discussions/7698), we've introduced some new APIs that give you more granular control over your fetcher behaviors.
- You may now specify your own fetcher identifier via `useFetcher({ key: string })`, which allows you to access the same fetcher instance from different components in your application without prop-drilling
- Fetcher keys are now exposed on the fetchers returned from `useFetchers` so that they can be looked up by `key`
- `Form` and `useSubmit` now support optional `navigate`/`fetcherKey` props/params to allow kicking off a fetcher submission under the hood with an optionally user-specified `key`
- `