You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -414,7 +414,7 @@ The biggest set of changes in `7.8.0` are to the `unstable_middleware` API's as
414
414
415
415
⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_
416
416
417
-
- `react-router` - **Middleware**: Change the `unstable_getContext` signature on `RouterProvider`/`HydratedRouter`/`unstable_RSCHydratedRouter` so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to construct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
417
+
- `react-router` - **Middleware**: Change the `unstable_getContext` signature on `RouterProvider`, `HydratedRouter`, and `unstable_RSCHydratedRouter` so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to construct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
418
418
- ⚠️ This is a breaking change if you have adopted the `unstable_getContext` prop
419
419
- `react-router` - **Middleware**: Run client middleware on client navigations even if no loaders exist ([#14106](https://github.com/remix-run/react-router/pull/14106))
420
420
- `react-router` - **Middleware**: Convert internal middleware implementations to use the new `unstable_generateMiddlewareResponse` API ([#14103](https://github.com/remix-run/react-router/pull/14103))
<docs-info>This API exists to mirror the `getLoadContext` API on the server in Framework Mode, which exists as a way to hand off values from your HTTP server to the React Router handler. This `unstable_getContext` API can be used to hand off global values from the `window`/`document` to React Router, but because they're all running in the same context (the browser), you can achieve effectively the the same behavior with a root route middleware. Therefore, you may not need this API the same way you would on the server - but it's provided for consistency.</docs-warning>
239
+
238
240
## Core Concepts
239
241
240
242
### Server vs Client Middleware
241
243
242
-
Server middleware runs on the server in Framework mode for HTML Document requests and `.data` requests for subsequent navigations and fetcher calls.
243
-
244
-
Because server middleware runs on the server in response to an HTTP `Request`, it returns an HTTP `Response` back up the middleware chain via the `next` function:
244
+
Server middleware runs on the server in Framework mode for HTML Document requests and `.data` requests for subsequent navigations and fetcher calls. Because server middleware runs on the server in response to an HTTP `Request`, it returns an HTTP `Response` back up the middleware chain via the `next` function:
**Client middleware** (`unstable_clientMiddleware`) runs in the browser in framework and data mode for:
258
-
259
-
- Client-side navigations and fetcher calls
260
-
261
-
Client middleware is different because there's no HTTP Request, so it doesn't bubble up anything via the `next` function:
258
+
Client middleware runs in the browser in framework and data mode for client-side navigations and fetcher calls. Client middleware is different because there's no HTTP Request, so it doesn't bubble up anything via the `next` function:
@@ -286,7 +283,7 @@ It is very important to understand _when_ your middlewares will run to make sure
286
283
287
284
#### Server Middleware
288
285
289
-
In a hydrated Framework Mode app, server middleware is designed such that it prioritizes SPA behavior and does not create new network activity by default. Middleware wraps _existing_request and only runs when you _need_ to hit the server.
286
+
In a hydrated Framework Mode app, server middleware is designed such that it prioritizes SPA behavior and does not create new network activity by default. Middleware wraps _existing_requests and only runs when you _need_ to hit the server.
290
287
291
288
This raises the question of what is a "handler" in React Router? Is it the route? Or the loader? We think "it depends":
292
289
@@ -314,7 +311,7 @@ function loggingMiddleware({ request }, next) {
However, there may be cases where you _want_ to run certain middlewares on _every_ client-navigation - even if no loader exists. For example, a form in the authenticated section of your site that doesn't require a `loader` but you'd rather use auth middleware to redirect users away before they fill out the form - rather then when they submit to the `action`. If your middleware meets this criteria, then you can put a `loader` on the route that contains the middleware to force it to always call the server for client side navigations involving that route.
314
+
However, there may be cases where you _want_ to run certain server middlewares on _every_ client-navigation - even if no loader exists. For example, a form in the authenticated section of your site that doesn't require a `loader` but you'd rather use auth middleware to redirect users away before they fill out the form - rather then when they submit to the `action`. If your middleware meets this criteria, then you can put a `loader` on the route that contains the middleware to force it to always call the server for client side navigations involving that route.
318
315
319
316
```tsx filename=app/_auth.tsx
320
317
function authMiddleware({ request }, next) {
@@ -334,11 +331,11 @@ export function loader() {
334
331
335
332
#### Client Middleware
336
333
337
-
Client middleware is simpler because since we are already on the client and are always making a "request" to the router when navigating, client middlewares will run on every client navigation, regardless of whether or not there are loaders to run.
334
+
Client middleware is simpler because since we are already on the client and are always making a "request" to the router when navigating. Client middlewares will run on every client navigation, regardless of whether or not there are loaders to run.
338
335
339
336
### Context API
340
337
341
-
The new context system provides type safety and prevents naming conflicts:
338
+
The new context system provides type safety and prevents naming conflicts and allows you to provide data to nested middlewares and loader/action functions. In Framework Mode, this replaces the previous `AppLoadContext` API.
React Router contains built-in error handling via the route [`ErrorBoundary`](../start/framework/route-module#errorboundary) export. Just like when a loader/acton throws, if a middleware throws an error it will be caught and handled at the appropriate `ErrorBoundary` and the `Response` will be returned through the ancestor `next()` call. This means that the `next()` function should never throw and should always return a `Response`, so you don't need to worry about wrapping it in a try/catch.
393
+
React Router contains built-in error handling via the route [`ErrorBoundary`](../start/framework/route-module#errorboundary) export. Just like when a loader/action throws, if a middleware throws an error it will be caught and handled at the appropriate `ErrorBoundary` and the `Response` will be returned through the ancestor `next()` call. This means that the `next()` function should never throw and should always return a `Response`, so you don't need to worry about wrapping it in a try/catch.
397
394
398
395
This behavior is important to allow middleware patterns such as automatically setting required headers on outgoing responses (i.e., committing a session) from a root middleware. If any error from a middleware caused `next()` to `throw`, we'd miss the execution of ancestor middlewares on the way out and those required headers wouldn't be set.
399
396
@@ -451,9 +448,9 @@ import { createDb } from "./db";
Copy file name to clipboardExpand all lines: docs/start/data/route-object.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,7 +56,7 @@ function MyRouteComponent() {
56
56
57
57
## `unstable_middleware`
58
58
59
-
Route middleware runs sequentially before and after navigations. This gives you a singular place to do things like logging and authentication. The `next` function continues down the chain, and on the leaf route the `next` function executes the loaders/actions for the navigation.
59
+
Route [middleware][middleware] runs sequentially before and after navigations. This gives you a singular place to do things like logging and authentication. The `next` function continues down the chain, and on the leaf route the `next` function executes the loaders/actions for the navigation.
Copy file name to clipboardExpand all lines: docs/start/framework/route-module.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -80,9 +80,9 @@ export default function MyRouteComponent({
80
80
81
81
## `unstable_middleware`
82
82
83
-
Route middleware runs sequentially on the server before and after document and
83
+
Route [middleware][middleware] runs sequentially on the server before and after document and
84
84
data requests. This gives you a singular place to do things like logging,
85
-
authentication, and post-processing of responses.
85
+
authentication, and post-processing of responses. The `next` function continues down the chain, and on the leaf route the `next` function executes the loaders/actions for the navigation.
86
86
87
87
Here's an example middleware to log requests on the server:
0 commit comments