Skip to content

Commit 0f06c66

Browse files
committed
Merge branch 'main' into release-next
2 parents 13abd80 + 768919a commit 0f06c66

File tree

8 files changed

+159
-21
lines changed

8 files changed

+159
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ Date: YYYY-MM-DD
379379

380380
## v7.9.5
381381

382-
Date: 2025-10-27
382+
Date: 2025-10-29
383383

384384
### What's Changed
385385

@@ -441,7 +441,7 @@ This release includes a new `unstable_useRoute()` hook that provides a type-safe
441441
### Patch Changes
442442

443443
- `@react-router/dev` - Update `valibot` dependency to `^1.1.0` ([#14379](https://github.com/remix-run/react-router/pull/14379))
444-
- `@react-router/node` - Validate format of incoming session ids ([#14426](https://github.com/remix-run/react-router/pull/14426))
444+
- `@react-router/node` - Validate format of incoming session ids in `createFileSessionStorage` ([#14426](https://github.com/remix-run/react-router/pull/14426))
445445

446446
### Unstable Changes
447447

GOVERNANCE.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,17 @@ This table gives a high-level overview of the stages, but please see the individ
107107
### Stage 1 — Consideration
108108

109109
- A proposal enters **Stage 1 — Consideration** when 2 SC members indicate interest/support for the idea as a valuable addition to React Router
110-
- Upon entering this stage, a GitHub Issue will be created for the feature and added to the roadmap
111110
- These initial supporting SC members will be the champions for the feature and will be loosely responsible for shepherding the feature through the stages of the RFC process
112111
- At this stage, the proposal is eligible for a sample PR implementation from a core team or community member
113112
- The SC will indicate at this stage if this is a feature open to a community PR or something the core team would prefer to tackle
113+
- We will add the `accepting-prs` label to the RFC if we are open to community PRs
114114
- All PRs at this stage should implement the feature in an "unstable" fashion (usually using an `unstable_` prefix on the future flag or API)
115115

116116
### Stage 2 — Alpha
117117

118118
- A proposal enters **Stage 2 — Alpha** once a PR has been opened implementing the feature in an `unstable_` state
119119
- At this stage, we should open an Issue for the Proposal and add it to the [Roadmap](https://github.com/orgs/remix-run/projects/5)
120+
- We will remove any `accepting-prs` label and add the `🗺️ Roadmap` label to indicate that this RFc is officially on the roadmap
120121
- At this stage, we are looking for early community testing _before_ merging any work to the React Router repo — so these PRs should provide a mechanism for community members to opt into to alpha testing
121122
- Maintainers can trigger an alpha release from the PR branch by adding the `alpha-release` label, which will kick off an experimental release and comment it back on the PR
122123
- Because the alpha release may contain other work committed to `dev` but not yet released in a stable version, it may not be ideal for testing in all cases
@@ -225,3 +226,24 @@ Matt Brophy, Bryan Ross (rossipedia), Mark Dalgleish, and Pedro Cattori discusse
225226
- Matt Brophy will try to pick up the [`<Link onPrefetch>`](https://github.com/remix-run/react-router/discussions/12375) task soon
226227
- Matt Brophy and Pedro Cattori will sync up offline to figure out what parts of the consolidated hook can be done better with typegen and decide on the requirements ([RFC](https://github.com/remix-run/react-router/issues/13073))
227228
</details>
229+
230+
<details>
231+
<summary>2025-11-04 Meeting Notes</summary>
232+
233+
The SC reviewed items on the open Proposal for React Router v8
234+
235+
- Confirmed the plan to drop CJS builds for ESM-only builds
236+
- We will plan RR v8 for Q2 2026 which aligns nicely with the EOL for Node 20
237+
- v8 will have a minimum Node version of 22.12 so that the `require(esm)` feature is not behind an [experimental flag](https://nodejs.org/docs/latest-v22.x/api/modules.html#loading-ecmascript-modules-using-require)
238+
- Going forward we will aim for a yearly major release in the same Q2 timeframe
239+
- We would like to try to get `useRouterState` into v8 as the other half of the `unstable_useRoute` coin
240+
- We think Subresource Integrity (SRI) is ready for stabilization but we would like to ping a few existing users and/or SME's to confirm the implementation is valid
241+
- Discussed the `unstable_optimizedDeps` feature, confirming it will remain unstable in V8 and then be pseudo-deprecated in favor of RollDown
242+
- There are some concerns about RollDown's full bundle mode limiting scalability so we may need to wait until rolldown is ready for testing
243+
- Decided against making "type-safe matches" an immediate V8 necessity due to the API churn
244+
- RSC implementation will not have a stable API ready for V8 but will be released in a minor version later
245+
- We will not be deprecating existing APIs at that time because not everyone should have to use RSC
246+
- `Vite environment API` and `split route modules` are nearing stabilization
247+
- Reviewed a new RFC to stop URL normalization in loaders
248+
249+
</details>

contributors.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
- gaspard
130130
- gatzjames
131131
- gavriguy
132+
- gchang12
132133
- Geist5000
133134
- GeoffKarnov
134135
- gesposito
@@ -322,6 +323,7 @@
322323
- pruszel
323324
- pwdcd
324325
- pyitphyoaung
326+
- QzCurious
325327
- redabacha
326328
- refusado
327329
- remorses

docs/api/framework-conventions/entry.server.tsx.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ order: 5
99

1010
## Summary
1111

12-
<docs-info>
13-
This file is optional
14-
</docs-info>
15-
1612
This file is the server-side entry point that controls how your React Router application generates HTTP responses on the server.
1713

1814
This module should render the markup for the current page using a [`<ServerRouter>`][serverrouter] element with the `context` and `url` for the current request. This markup will (optionally) be re-hydrated once JavaScript loads in the browser using the [client entry module][client-entry].
1915

16+
<docs-info>This file is optional if you are running on Node. If it is not present, a [default implementation][node-streaming-entry-server] will be used.
17+
<br/>
18+
<br/>
19+
If you are using another runtime (i.e., Cloudflare) then you need to include this file. You can find sample implementations in the [templates repository][templates-repo].</docs-info>
20+
2021
## Generating `entry.server.tsx`
2122

22-
By default, React Router will handle generating the HTTP Response for you. You can reveal the default entry server file with the following:
23+
When running in Node, React Router will handle generating the HTTP Response for you. You can reveal the default entry server file with the following:
2324

2425
```shellscript nonumber
2526
npx react-router reveal
@@ -42,7 +43,7 @@ export default function handleRequest(
4243
request: Request,
4344
responseStatusCode: number,
4445
responseHeaders: Headers,
45-
routerContext: EntryContext
46+
routerContext: EntryContext,
4647
) {
4748
return new Promise((resolve, reject) => {
4849
const { pipe, abort } = renderToPipeableStream(
@@ -62,15 +63,15 @@ export default function handleRequest(
6263
new Response(stream, {
6364
headers: responseHeaders,
6465
status: responseStatusCode,
65-
})
66+
}),
6667
);
6768

6869
pipe(body);
6970
},
7071
onShellError(error: unknown) {
7172
reject(error);
7273
},
73-
}
74+
},
7475
);
7576
});
7677
}
@@ -113,7 +114,7 @@ export function handleDataRequest(
113114
request,
114115
params,
115116
context,
116-
}: LoaderFunctionArgs | ActionFunctionArgs
117+
}: LoaderFunctionArgs | ActionFunctionArgs,
117118
) {
118119
response.headers.set("X-Custom-Header", "value");
119120
return response;
@@ -131,7 +132,7 @@ export function handleError(
131132
request,
132133
params,
133134
context,
134-
}: LoaderFunctionArgs | ActionFunctionArgs
135+
}: LoaderFunctionArgs | ActionFunctionArgs,
135136
) {
136137
if (!request.signal.aborted) {
137138
sendErrorToErrorReportingService(error);
@@ -155,8 +156,9 @@ For an example, please refer to the default [`entry.server.tsx`][node-streaming-
155156
Note that this does not handle thrown `Response` instances from your `loader`/`action` functions. The intention of this handler is to find bugs in your code which result in unexpected thrown errors. If you are detecting a scenario and throwing a 401/404/etc. `Response` in your `loader`/`action` then it's an expected flow that is handled by your code. If you also wish to log, or send those to an external service, that should be done at the time you throw the response.
156157

157158
[client-entry]: ./entry.client.tsx
158-
[serverrouter]: ../components/ServerRouter
159-
[streaming]: ../how-to/suspense
159+
[serverrouter]: ../framework-routers/ServerRouter
160+
[streaming]: ../../how-to/suspense
160161
[rendertopipeablestream]: https://react.dev/reference/react-dom/server/renderToPipeableStream
161162
[rendertoreadablestream]: https://react.dev/reference/react-dom/server/renderToReadableStream
162163
[node-streaming-entry-server]: https://github.com/remix-run/react-router/blob/dev/packages/react-router-dev/config/defaults/entry.server.node.tsx
164+
[templates-repo]: https://github.com/remix-run/react-router-templates

docs/how-to/error-boundary.md

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ All applications should at a minimum export a root error boundary. This one hand
2121
- Instances of errors with a stack trace
2222
- Randomly thrown values
2323

24-
```tsx filename=root.tsx
24+
### Framework Mode
25+
26+
[modes: framework]
27+
28+
In [Framework Mode][picking-a-mode], errors are passed to the route-level error boundary as a prop (see [`Route.ErrorBoundaryProps`][type-safety]), so you don't need to use a hook to grab it:
29+
30+
```tsx filename=root.tsx lines=[1,3-5]
2531
import { Route } from "./+types/root";
2632

2733
export function ErrorBoundary({
@@ -51,8 +57,57 @@ export function ErrorBoundary({
5157
}
5258
```
5359

60+
### Data Mode
61+
62+
[modes: data]
63+
64+
In [Data Mode][picking-a-mode], the `ErrorBoundary` doesn't receive props, so you can access it via `useRouteError`:
65+
66+
```tsx lines=[1,6,16]
67+
import { useRouteError } from "react-router";
68+
69+
let router = createBrowserRouter([
70+
{
71+
path: "/",
72+
ErrorBoundary: RootErrorBoundary,
73+
Component: Root,
74+
},
75+
]);
76+
77+
function Root() {
78+
/* ... */
79+
}
80+
81+
function RootErrorBoundary() {
82+
let error = useRouteError();
83+
if (isRouteErrorResponse(error)) {
84+
return (
85+
<>
86+
<h1>
87+
{error.status} {error.statusText}
88+
</h1>
89+
<p>{error.data}</p>
90+
</>
91+
);
92+
} else if (error instanceof Error) {
93+
return (
94+
<div>
95+
<h1>Error</h1>
96+
<p>{error.message}</p>
97+
<p>The stack trace is:</p>
98+
<pre>{error.stack}</pre>
99+
</div>
100+
);
101+
} else {
102+
return <h1>Unknown Error</h1>;
103+
}
104+
}
105+
```
106+
54107
## 2. Write a bug
55108

109+
[modes: framework,data]
110+
56111
It's not recommended to intentionally throw errors to force the error boundary to render as a means of control flow. Error Boundaries are primarily for catching unintentional errors in your code.
57112

58113
```tsx
@@ -67,6 +122,8 @@ This is not just for loaders, but for all route module APIs: loaders, actions, c
67122

68123
## 3. Throw data in loaders/actions
69124

125+
[modes: framework,data]
126+
70127
There are exceptions to the rule in #2, especially 404s. You can intentionally `throw data()` (with a proper status code) to the closest error boundary when your loader can't find what it needs to render the page. Throw a 404 and move on.
71128

72129
```tsx
@@ -85,7 +142,13 @@ This will render the `isRouteErrorResponse` branch of the UI from step 1.
85142

86143
## 4. Nested error boundaries
87144

88-
When an error is thrown, the "closest error boundary" will be rendered. Consider these nested routes:
145+
When an error is thrown, the "closest error boundary" will be rendered.
146+
147+
### Framework Mode
148+
149+
[modes: framework]
150+
151+
Consider these nested routes:
89152

90153
```tsx filename="routes.ts"
91154
// ✅ has error boundary
@@ -110,10 +173,59 @@ The following table shows which error boundary will render given the origin of t
110173
| invoice-page.tsx | invoice-page.tsx |
111174
| payments.tsx | invoice-page.tsx |
112175

176+
### Data Mode
177+
178+
[modes: data]
179+
180+
In Data Mode, the equivalent route tree might look like:
181+
182+
```tsx
183+
let router = createBrowserRouter([
184+
{
185+
path: "/app",
186+
Component: App,
187+
ErrorBoundary: AppErrorBoundary, // ✅ has error boundary
188+
children: [
189+
{
190+
path: "invoices",
191+
Component: Invoices, // ❌ no error boundary
192+
children: [
193+
{
194+
path: ":id",
195+
Component: Invoice,
196+
ErrorBoundary: InvoiceErrorBoundary, // ✅ has error boundary
197+
children: [
198+
{
199+
path: "payments",
200+
Component: Payments, // ❌ no error boundary
201+
},
202+
],
203+
},
204+
],
205+
},
206+
],
207+
},
208+
]);
209+
```
210+
211+
The following table shows which error boundary will render given the origin of the error:
212+
213+
| error origin | rendered boundary |
214+
| ------------ | ---------------------- |
215+
| `App` | `AppErrorBoundary` |
216+
| `Invoices` | `AppErrorBoundary` |
217+
| `Invoice` | `InvoiceErrorBoundary` |
218+
| `Payments` | `InvoiceErrorBoundary` |
219+
113220
## Error Sanitization
114221

115-
In production mode, any errors that happen on the server are automatically sanitized before being sent to the browser to prevent leaking any sensitive server information (like stack traces).
222+
[modes: framework]
223+
224+
In Framework Mode when building for production, any errors that happen on the server are automatically sanitized before being sent to the browser to prevent leaking any sensitive server information (like stack traces).
116225

117226
This means that a thrown `Error` will have a generic message and no stack trace in production in the browser. The original error is untouched on the server.
118227

119228
Also note that data sent with `throw data(yourData)` is not sanitized as the data there is intended to be rendered.
229+
230+
[picking-a-mode]: ../start/modes
231+
[type-safety]: ../explanation/type-safety

docs/start/framework/data-loading.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export default function Product({
106106
}
107107
```
108108

109-
The URLs to pre-render are specified in react-router.config.ts:
109+
The URLs to pre-render are specified in `react-router.config.ts`:
110110

111111
```ts filename=react-router.config.ts
112112
import type { Config } from "@react-router/dev/config";

docs/start/framework/route-module.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ The meta of the last matching route is used, allowing you to override parent rou
480480

481481
## `shouldRevalidate`
482482

483-
In framework mode with SSR, route loaders are automatically revalidated after all navigations and form submissions (this is different from [Data Mode][data-mode-should-revalidate]). This enables middleware and loaders to share a request context and optimize in different ways than then they would be in Data Mode.
483+
In framework mode with SSR, route loaders are automatically revalidated after all navigations and form submissions (this is different from [Data Mode][data-mode-should-revalidate]). This enables middleware and loaders to share a request context and optimize in different ways than they would in Data Mode.
484484

485485
Defining this function allows you to opt out of revalidation for a route loader for navigations and form submissions.
486486

packages/react-router-node/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
### Patch Changes
1313

14-
- Validate format of incoming session ids ([#14426](https://github.com/remix-run/react-router/pull/14426))
14+
- Validate format of incoming session ids in `createFileSessionStorage` ([#14426](https://github.com/remix-run/react-router/pull/14426))
1515
- Updated dependencies:
1616
- `react-router@7.9.4`
1717

0 commit comments

Comments
 (0)