Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
237782c
Merge branch 'release' into dev
brophdawg11 Apr 21, 2026
9cc0311
chore: format
remix-run-bot Apr 21, 2026
596655c
fix: make unstable_mask optional in Location (#14995)
Quatton Apr 21, 2026
0ff8854
Remove temp restriction for change file workflow
brophdawg11 Apr 22, 2026
226e355
Add links to comments
brophdawg11 Apr 22, 2026
cbbc6fc
perf: cache flattened/ranked route branches (#14967)
brophdawg11 Apr 22, 2026
9e9b622
Update pnpm/actions-setuip to v6
brophdawg11 Apr 22, 2026
0e495d5
Add issues:write permission to change file check workflow
brophdawg11 Apr 28, 2026
10a9686
Migrate changeset to change file
brophdawg11 Apr 28, 2026
6f18edd
Add nonce to scripts `modulepreload` (#15002)
Abdulwahaab710 Apr 29, 2026
67518cb
Remove unnecessary hasShouldRevalidate condition for opting out (#15012)
dadamssg May 4, 2026
5f61543
Client-side route matching optimizations (#14971)
brophdawg11 May 4, 2026
51a79a4
chore: generate markdown docs from jsdocs
remix-run-bot May 4, 2026
49295b5
Stabilize APIs (#14999)
brophdawg11 May 4, 2026
e756132
chore: format
remix-run-bot May 4, 2026
35dccb4
chore: generate markdown docs from jsdocs
remix-run-bot May 4, 2026
362635b
Move chnageset to change file
brophdawg11 May 4, 2026
bd35829
Merge branch 'main' into release
brophdawg11 May 4, 2026
51a9ccd
Update react router serve docs
brophdawg11 May 5, 2026
9869208
More docs updates
brophdawg11 May 5, 2026
a993f09
Update change files
brophdawg11 May 5, 2026
af5d49b
Update change files again
brophdawg11 May 5, 2026
97c8de7
Release v7.15.0 (#15018)
ryanflorence May 5, 2026
20dd4bc
Merge branch 'release'
brophdawg11 May 5, 2026
e9d0d4e
chore: format
remix-run-bot May 5, 2026
2ba36dc
Update release notes
brophdawg11 May 5, 2026
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
71 changes: 71 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ We manage release notes in this file instead of the paginated Github Releases Pa
<summary>Table of Contents</summary>

- [React Router Releases](#react-router-releases)
- [v7.15.0](#v7150)
- [v7.14.2](#v7142)
- [v7.14.1](#v7141)
- [v7.14.0](#v7140)
Expand Down Expand Up @@ -169,6 +170,76 @@ We manage release notes in this file instead of the paginated Github Releases Pa

</details>

## v7.15.0

Date: 2026-05-05

### What's Changed

#### Stabilizations

We've stabilized a bunch of APIs in this release in preparation for a React Router v8 release hopefully in the next month or two. These flag/prop renames are breaking changes if you've already opted into the unstable APIs so please make sure you make the appropriate changes if so.

- `future.unstable_passThroughRequests` → `future.v8_passThroughRequests`
- `future.unstable_subResourceIntegrity` → top-level `config.subResourceIntegrity`
- `prerender.unstable_concurrency` → `prerender.concurrency`
- `unstable_url` → `url` (loader, action, middleware, instrumentation args)
- `unstable_instrumentations` → `instrumentations`
- Plus associated types (`ServerInstrumentation`, `ClientInstrumentation`, etc.)
- `unstable_pattern` → `pattern` (loader, action, middleware, instrumentation args)
- `unstable_defaultShouldRevalidate` → `defaultShouldRevalidate`
- `unstable_useTransitions` → `useTransitions`
- `unstable_mask` → `mask` (on `<Link>`, `useLinkClickHandler`, `useNavigate`, and `Location`)

#### Route matching optimizations

We've added a handful of route matching optimizations in this release for Framework and Data mode. The changes are mostly related to caching the internal flattened/ranked route branches and reducing additional calls to `matchRoutes` along the critical path. This should result in improved performance during both server-side request handling and client-side navigations.

### Minor Changes

- `react-router` - Stabilize `unstable_defaultShouldRevalidate` as `defaultShouldRevalidate` on `<Link>`, `<Form>`, `useLinkClickHandler`, `useSubmit`, `fetcher.submit`, and `setSearchParams` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Stabilize the instrumentation APIs ([14999](https://github.com/remix-run/react-router/pull/14999))
- `unstable_instrumentations` is now `instrumentations`
- `unstable_pattern` is now `pattern`
- The `unstable_ServerInstrumentation`, `unstable_ClientInstrumentation`, `unstable_InstrumentRequestHandlerFunction`, `unstable_InstrumentRouterFunction`, `unstable_InstrumentRouteFunction`, and `unstable_InstrumentationHandlerResult` types have had their `unstable_` prefixes removed
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Stabilize `unstable_mask` as `mask` on `<Link>`, `useLinkClickHandler`, and `useNavigate`, and rename the corresponding `Location.unstable_mask` field to `Location.mask` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Stabilize the `unstable_normalizePath` option on `staticHandler.query` and `staticHandler.queryRoute` as `normalizePath` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Stabilize `future.unstable_passThroughRequests` as `future.v8_passThroughRequests` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Remove `unstable_subResourceIntegrity` from the runtime `FutureConfig` type; the flag is now controlled by the top-level `subResourceIntegrity` option in `react-router.config.ts` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Stabilize `unstable_url` as `url` on `loader`, `action`, and `middleware` function args ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `react-router` - Stabilize `unstable_useTransitions` as `useTransitions` on `<BrowserRouter>`, `<HashRouter>`, `<HistoryRouter>`, `<MemoryRouter>`, `<Router>`, `<RouterProvider>`, `<HydratedRouter>`, and `useLinkClickHandler` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `@react-router/dev` - Stabilize `future.unstable_passThroughRequests` as `future.v8_passThroughRequests` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `@react-router/dev` - Stabilize `prerender.unstable_concurrency` as `prerender.concurrency` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly
- `@react-router/dev` - Stabilize `future.unstable_subResourceIntegrity` as a top-level `subResourceIntegrity` config option in `react-router.config.ts` ([14999](https://github.com/remix-run/react-router/pull/14999))
- ⚠️ This is a breaking change if you have already opted into the unstable version - you will need to update your code accordingly

### Patch Changes

- `react-router` - Add `nonce` to `<Scripts>` `<link rel="modulepreload">` elements (if provided) ([af5d49b](https://github.com/remix-run/react-router/commit/af5d49b))
- `react-router` - Fix a bug with `unstable_defaultShouldRevalidate={false}` where parent routes that did not export a `shouldRevalidate` function could be incorrectly included in the single fetch call for new child route data ([#15012](https://github.com/remix-run/react-router/pull/15012))
- `react-router` - Mark `mask` as an optional field in `Location` for easier mocking in unit tests ([#14999](https://github.com/remix-run/react-router/pull/14999))
- `react-router` - Improve server-side route matching performance by pre-computing flattened/cached route branches ([#14967](https://github.com/remix-run/react-router/pull/14967)) ([af5d49b](https://github.com/remix-run/react-router/commit/af5d49b))
- Performance benchmarks showed roughly a 10-15% improvement in server-side request handling performance
- `react-router` - Cache flattened/ranked route branches to optimize server-side route matching ([#14967](https://github.com/remix-run/react-router/pull/14967))
- `react-router` - Improve route matching performance in Framework/Data Mode ([#14971](https://github.com/remix-run/react-router/pull/14971)) ([af5d49b](https://github.com/remix-run/react-router/commit/af5d49b))
- Avoiding unnecessary calls to `matchRoutes` in data router scenarios
- This includes adding back the optimization that was removed in `7.6.0` ([#13562](https://github.com/remix-run/react-router/pull/13562))
- The issues that prompted the revert have been addressed by using the available router `matches` but always updating `match.route` to the latest route in the `manifest`
- Leverage pre-computed pre-computing flattened/cached route branches during client side route matching
- Performance benchmarks showed roughly a 15-30% improvement in server-side request handling performance

**Full Changelog**: [`v7.14.2...v7.15.0`](https://github.com/remix-run/react-router/compare/react-router@7.14.2...react-router@7.15.0)

## v7.14.2

Date: 2026-04-21
Expand Down
2 changes: 2 additions & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- 43081j
- aarbi
- abdallah-nour
- abdulwahaab710
- abeadam
- abhi-kr-2100
- abhijeetpandit7
Expand Down Expand Up @@ -349,6 +350,7 @@
- pwdcd
- pyitphyoaung
- qu0b
- Quatton
- QzCurious
- raphaelbronsveld
- redabacha
Expand Down
2 changes: 1 addition & 1 deletion decisions/0015-observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ let unInstrumentedHandler = createRequestHandler({
...m.entry,
module: {
...m.entry.module,
unstable_instrumentations: undefined,
instrumentations: undefined,
},
},
})),
Expand Down
2 changes: 1 addition & 1 deletion docs/api/components/Form.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Enables a [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/Vie
for this navigation. To apply specific styles during the transition, see
[`useViewTransitionState`](../hooks/useViewTransitionState).

### unstable_defaultShouldRevalidate
### defaultShouldRevalidate

Specify the default revalidation behavior after this submission

Expand Down
8 changes: 4 additions & 4 deletions docs/api/components/Link.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,14 @@ for this navigation.

To apply specific styles for the transition, see [`useViewTransitionState`](../hooks/useViewTransitionState)

### unstable_defaultShouldRevalidate
### defaultShouldRevalidate

[modes: framework, data, declarative]

Specify the default revalidation behavior for the navigation.

```tsx
<Link to="/some/path" unstable_defaultShouldRevalidate={false} />
<Link to="/some/path" defaultShouldRevalidate={false} />
```

If no `shouldRevalidate` functions are present on the active routes, then this
Expand All @@ -232,7 +232,7 @@ useful when updating search params and you don't want to trigger a revalidation.
By default (when not specified), loaders will revalidate according to the routers
standard revalidation behavior.

### unstable_mask
### mask

[modes: framework, data]

Expand Down Expand Up @@ -265,7 +265,7 @@ export default function Gallery({ loaderData }: Route.ComponentProps) {
<Link
key={image.id}
to={`/gallery?image=${image.id}`}
unstable_mask={`/images/${image.id}`}
mask={`/images/${image.id}`}
>
<img src={image.url} alt={image.alt} />
</Link>
Expand Down
8 changes: 4 additions & 4 deletions docs/api/data-routers/RouterProvider.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function RouterProvider({
router,
flushSync: reactDomFlushSyncImpl,
onError,
unstable_useTransitions,
useTransitions,
}: RouterProviderProps): React.ReactElement
```

Expand Down Expand Up @@ -78,7 +78,7 @@ and is only present for render errors.

```tsx
<RouterProvider onError=(error, info) => {
let { location, params, unstable_pattern, errorInfo } = info;
let { location, params, pattern, errorInfo } = info;
console.error(error, location, errorInfo);
reportToErrorService(error, location, errorInfo);
}} />
Expand All @@ -88,7 +88,7 @@ and is only present for render errors.

The [`DataRouter`](https://api.reactrouter.com/v7/interfaces/react-router.DataRouter.html) instance to use for navigation and data fetching.

### unstable_useTransitions
### useTransitions

Control whether router state updates are internally wrapped in
[`React.startTransition`](https://react.dev/reference/react/startTransition).
Expand All @@ -105,5 +105,5 @@ Control whether router state updates are internally wrapped in
- When set to `false`, the router will not leverage `React.startTransition` or
`React.useOptimistic` on any navigations or state changes.

For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
For more information, please see the [docs](../../explanation/react-transitions).

4 changes: 2 additions & 2 deletions docs/api/data-routers/createBrowserRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ const router = createBrowserRouter(
);
```

### opts.unstable_instrumentations
### opts.instrumentations

Array of instrumentation objects allowing you to instrument the router and
individual routes prior to router initialization (and on any subsequently
Expand All @@ -183,7 +183,7 @@ tracing. See the [docs](../../how-to/instrumentation) for more information.

```tsx
let router = createBrowserRouter(routes, {
unstable_instrumentations: [logging]
instrumentations: [logging]
});


Expand Down
4 changes: 2 additions & 2 deletions docs/api/data-routers/createHashRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const router = createBrowserRouter(
);
```

### opts.unstable_instrumentations
### opts.instrumentations

Array of instrumentation objects allowing you to instrument the router and
individual routes prior to router initialization (and on any subsequently
Expand All @@ -153,7 +153,7 @@ tracing. See the [docs](../../how-to/instrumentation) for more information.

```tsx
let router = createBrowserRouter(routes, {
unstable_instrumentations: [logging]
instrumentations: [logging]
});


Expand Down
4 changes: 2 additions & 2 deletions docs/api/data-routers/createMemoryRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Initial entries in the in-memory history stack

Index of `initialEntries` the application should initialize to

### opts.unstable_instrumentations
### opts.instrumentations

Array of instrumentation objects allowing you to instrument the router and
individual routes prior to router initialization (and on any subsequently
Expand All @@ -110,7 +110,7 @@ tracing. See the [docs](../../how-to/instrumentation) for more information.

```tsx
let router = createBrowserRouter(routes, {
unstable_instrumentations: [logging]
instrumentations: [logging]
});


Expand Down
5 changes: 5 additions & 0 deletions docs/api/data-routers/createStaticRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function createStaticRouter(
routes: RouteObject[],
context: StaticHandlerContext,
opts: {
branches?: RouteBranch<DataRouteObject>[];
future?: Partial<FutureConfig>;
} = ,
): DataRouter {}
Expand All @@ -67,6 +68,10 @@ The [`StaticHandlerContext`](https://api.reactrouter.com/v7/interfaces/react-rou

Future flags for the static [`DataRouter`](https://api.reactrouter.com/v7/interfaces/react-router.DataRouter.html)

### opts.branches

Optional pre-computed route branches

## Returns

A static [`DataRouter`](https://api.reactrouter.com/v7/interfaces/react-router.DataRouter.html) that can be used to render the provided routes
Expand Down
6 changes: 3 additions & 3 deletions docs/api/declarative-routers/BrowserRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ API for client-side routing.
function BrowserRouter({
basename,
children,
unstable_useTransitions,
useTransitions,
window,
}: BrowserRouterProps)
```
Expand All @@ -46,7 +46,7 @@ Application basename

``<Route>`` components describing your route configuration

### unstable_useTransitions
### useTransitions

Control whether router state updates are internally wrapped in
[`React.startTransition`](https://react.dev/reference/react/startTransition).
Expand All @@ -59,7 +59,7 @@ Control whether router state updates are internally wrapped in
- When set to `false`, the router will not leverage `React.startTransition`
on any navigations or state changes.

For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
For more information, please see the [docs](../../explanation/react-transitions).

### window

Expand Down
6 changes: 3 additions & 3 deletions docs/api/declarative-routers/HashRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ of the URL so it is not sent to the server.
function HashRouter({
basename,
children,
unstable_useTransitions,
useTransitions,
window,
}: HashRouterProps)
```
Expand All @@ -47,7 +47,7 @@ Application basename

``<Route>`` components describing your route configuration

### unstable_useTransitions
### useTransitions

Control whether router state updates are internally wrapped in
[`React.startTransition`](https://react.dev/reference/react/startTransition).
Expand All @@ -60,7 +60,7 @@ Control whether router state updates are internally wrapped in
- When set to `false`, the router will not leverage `React.startTransition`
on any navigations or state changes.

For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
For more information, please see the [docs](../../explanation/react-transitions).

### window

Expand Down
6 changes: 3 additions & 3 deletions docs/api/declarative-routers/HistoryRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function HistoryRouter({
basename,
children,
history,
unstable_useTransitions,
useTransitions,
}: HistoryRouterProps)
```

Expand All @@ -61,7 +61,7 @@ Application basename

A `History` implementation for use by the router

### unstable_useTransitions
### useTransitions

Control whether router state updates are internally wrapped in
[`React.startTransition`](https://react.dev/reference/react/startTransition).
Expand All @@ -74,5 +74,5 @@ Control whether router state updates are internally wrapped in
- When set to `false`, the router will not leverage `React.startTransition`
on any navigations or state changes.

For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
For more information, please see the [docs](../../explanation/react-transitions).

6 changes: 3 additions & 3 deletions docs/api/declarative-routers/MemoryRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function MemoryRouter({
children,
initialEntries,
initialIndex,
unstable_useTransitions,
useTransitions,
}: MemoryRouterProps): React.ReactElement
```

Expand All @@ -54,7 +54,7 @@ Initial entries in the in-memory history stack

Index of `initialEntries` the application should initialize to

### unstable_useTransitions
### useTransitions

Control whether router state updates are internally wrapped in
[`React.startTransition`](https://react.dev/reference/react/startTransition).
Expand All @@ -67,5 +67,5 @@ Control whether router state updates are internally wrapped in
- When set to `false`, the router will not leverage `React.startTransition`
on any navigations or state changes.

For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
For more information, please see the [docs](../../explanation/react-transitions).

6 changes: 3 additions & 3 deletions docs/api/declarative-routers/Router.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function Router({
navigationType = NavigationType.Pop,
navigator,
static: staticProp = false,
unstable_useTransitions,
useTransitions,
}: RouterProps): React.ReactElement | null
```

Expand Down Expand Up @@ -72,7 +72,7 @@ or a custom navigator that implements the [`Navigator`](https://api.reactrouter.
Whether this router is static or not (used for SSR). If `true`, the router
will not be reactive to location changes.

### unstable_useTransitions
### useTransitions

Control whether router state updates are internally wrapped in
[`React.startTransition`](https://react.dev/reference/react/startTransition).
Expand All @@ -85,5 +85,5 @@ Control whether router state updates are internally wrapped in
- When set to `false`, the router will not leverage `React.startTransition`
on any navigations or state changes.

For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
For more information, please see the [docs](../../explanation/react-transitions).

Loading