Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 33 additions & 16 deletions docs/upgrading/v7.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ order: 2

# Upgrading from v7

We try our best to keep major version upgrades simple and boring through the use of opt-in APIs and [Future Flags][api-development-strategy]. Future flags are used to gate breaking changes that don't otherwise have a good call-site opt-in strategy. By adopting all opt-in APIs and future flags, you should be able to upgrade to the next major version of React Router with minimal changes.
We try our best to keep major version upgrades simple and boring through the use of opt-in APIs and [Future Flags][api-development-strategy]. Future flags are used to gate breaking changes that don't otherwise have a good call-site opt-in strategy. By adopting all opt-in APIs and future flags while still on v7, you should be able to update to React Router v8 with minimal changes.

We highly recommend you make a commit after each step and ship it instead of doing everything all at once. Most flags can be adopted in any order, with exceptions noted below.

Expand All @@ -16,19 +16,19 @@ We highly recommend you make a commit after each step and ship it instead of doi
<br/>
<br/>

React Router v8 requires the following minimum versions. You can prepare for the upgrade by updating them while still on v7:
React Router v8 requires the following minimum versions. Update them before updating React Router to v8:

- `node@22.22+`
- `react@19.2.7+`/`react-dom@19.2.7+`

Framework mode will also require:
Framework mode also requires:

- `vite@7+` (requires `future.v8_viteEnvironmentApi`)
- also make sure any custom Vite plugins or config are compatible with Vite 7

## Update to latest v7.x

Before adopting any future flags or call-site opt-in changes, you should update to the latest minor version of v7.x to make sure you have access to the latest flags. You may see a number of deprecation warnings as you upgrade, which we'll cover below.
Before adopting any future flags or call-site opt-in changes, update to the latest minor version of v7.x to make sure you have access to the latest flags. You may see a number of deprecation warnings as you upgrade, which we'll cover below.

👉 Update to latest v7

Expand Down Expand Up @@ -243,7 +243,7 @@ export async function loader({

React Router serves Framework mode data requests from `.data` URLs. Previously, data requests for routes with and without trailing slashes could map to the same `.data` URL because trailing slashes were not considered during URL generation. This flag preserves trailing slash semantics for data request URLs to avoid ambiguity when your app distinguishes between trailing-slash and non-trailing-slash URLs.

Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` and `/a/b/c/`
In v7, your HTTP and `request` pathnames are as follows for `/a/b/c` and `/a/b/c/`

| URL `/a/b/c` | **HTTP pathname** | **`request` pathname`** |
| ------------ | ----------------- | ----------------------- |
Expand All @@ -255,7 +255,7 @@ Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` an
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
| **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |

With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
With this flag enabled, these pathnames are made consistent through a new `_.data` format for client-side `.data` requests:

| URL `/a/b/c` | **HTTP pathname** | **`request` pathname`** |
| ------------ | ----------------- | ----------------------- |
Expand Down Expand Up @@ -285,11 +285,11 @@ export default {

If you have custom app, CDN, cache, or rewrite logic that matches `.data` request URLs, update it to handle the new trailing-slash-aware `/_.data` format.

## Other Planned Breaking Changes
## Other Breaking Changes

The changes in this section are not controlled by future flags, but you can update your code in v7 to be ready for v8.
The changes in this section are not controlled by future flags, but you can update your code while still on v7 before moving to v8.

### `meta` `data` Argument
### `meta`/`matches` `data` Values

[MODES: framework]

Expand All @@ -298,7 +298,13 @@ The changes in this section are not controlled by future flags, but you can upda

**Background**

The `data` fields passed to route module `meta` functions are deprecated and will be removed in React Router v8. Use `loaderData` instead on `MetaArgs` and each item in `MetaArgs.matches`.
React Router v8 removed deprecated `data` fields in favor of `loaderData` in a few places:

- `meta` function `data` argument
- `meta` function `matches` argument (`matches[i].data`)
- `useMatches()` (`matches[i].data`)

Use `loaderData` instead on `MetaArgs`, each item in `MetaArgs.matches`, and each match returned from `useMatches()`

👉 **Update your Code**

Expand Down Expand Up @@ -331,6 +337,17 @@ export function meta({ matches }: Route.MetaArgs) {
}
```

Replace `data` with `loaderData` on `useMatches()` calls:

```diff
export default function Component({ matches, loaderData }: ComponentProps) {
let matches = useMatches();
- const rootLoaderData = matches[0].data;
+ const rootLoaderData = matches[0].loaderData;
// ...
}
```

### `react-router-dom`

[MODES: framework, data, declarative]
Expand All @@ -340,7 +357,7 @@ export function meta({ matches }: Route.MetaArgs) {

**Background**

React Router v8 will remove the `react-router-dom` re-export package. In v8, you should import DOM-specific APIs from `react-router/dom` and everything else from `react-router`.
React Router v8 removes the `react-router-dom` re-export package. In v8, you should import DOM-specific APIs from `react-router/dom` and everything else from `react-router`.

👉 **Update your Code**

Expand Down Expand Up @@ -373,7 +390,7 @@ For DOM-specific APIs, import from `react-router/dom`:

**Background**

React Router v8 will remove the React Router Cloudflare dev proxy. Cloudflare projects should use [`@cloudflare/vite-plugin`][cloudflare-vite-plugin] instead.
React Router v8 removes the React Router Cloudflare dev proxy. Cloudflare projects should use [`@cloudflare/vite-plugin`][cloudflare-vite-plugin] instead.

👉 **Update your Code**

Expand Down Expand Up @@ -403,11 +420,11 @@ export default defineConfig({

**Background**

The `@react-router/architect` adapter currently uses `X-Forwarded-Host` when creating the `request`, falling back to the `Host` header. In React Router v8, the adapter will use `event.requestContext.domainName` by default, falling back to the `Host` header.
In v7, the `@react-router/architect` adapter uses `X-Forwarded-Host` when creating the `request`, falling back to the `Host` header. In React Router v8, the adapter uses `event.requestContext.domainName` by default, falling back to the `Host` header.

👉 **Update your Code**

Opt in to the v8 behavior now by passing `useRequestContextDomainName: true`:
Opt in to the v8 behavior while still on v7 by passing `useRequestContextDomainName: true`:

```ts
import { createRequestHandler } from "@react-router/architect";
Expand All @@ -419,11 +436,11 @@ export const handler = createRequestHandler({
});
```

This option will be removed in v8 once the `event.requestContext.domainName` behavior is the default.
This option is removed in v8 because the `event.requestContext.domainName` behavior is the default.

## Upgrade to v8

Now that your app is caught up, you can simply update to v8 (theoretically!) without issue.
Now that your app is caught up, update to v8:

```shellscript nonumber
# data/declarative mode
Expand Down