(null);
```
-### 2. Add middleware to your routes
+### 3. Add `middleware` to route objects
+
+Attach `middleware` arrays to your route objects:
```tsx
-import { redirect } from "react-router";
+import {
+ redirect,
+ useLoaderData,
+ type LoaderFunctionArgs,
+} from "react-router";
import { userContext } from "~/context";
const routes = [
@@ -159,10 +175,10 @@ const routes = [
Component: Root,
children: [
{
- path: "profile",
+ path: "dashboard",
middleware: [authMiddleware], // 👈
- loader: profileLoader,
- Component: Profile,
+ loader: dashboardLoader,
+ Component: Dashboard,
},
{
path: "login",
@@ -187,15 +203,15 @@ async function authMiddleware({ context }) {
context.set(userContext, user);
}
-export async function profileLoader({
+export async function dashboardLoader({
context,
-}: Route.LoaderArgs) {
+}: LoaderFunctionArgs) {
const user = context.get(userContext);
const profile = await getProfile(user);
return { profile };
}
-export default function Profile() {
+export default function Dashboard() {
let loaderData = useLoaderData();
return (
@@ -206,9 +222,9 @@ export default function Profile() {
}
```
-### 3. Add a `getContext` function (optional)
+### 4. Add a `getContext` function (optional)
-If you wish to include a base context on all navigations/fetches, you can add an [`getContext`][getContext] function to your router. This will be called to populate a fresh context on every navigation/fetch.
+To seed every navigation or fetcher call with shared values, pass [`getContext`][getContext] when creating the router:
```tsx
let sessionContext = createContext();
@@ -222,7 +238,7 @@ const router = createBrowserRouter(routes, {
});
```
-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 [`getContext`][getContext] API can be used to hand off global values from the [`window`][window]/[`document`][document] to React Router, but because they're all running in the same context (the browser), you can achieve effectively the same behavior with root route middleware. Therefore, you may not need this API the same way you would on the server - but it's provided for consistency.
+This mirrors Framework mode’s server-side [`getLoadContext`][getloadcontext]. In the browser, root `middleware` can often do the same job, but `getContext` is available when you want to seed every request up front.
## Core Concepts
@@ -250,7 +266,7 @@ Client middleware runs in the browser in framework and data mode for client-side
async function clientMiddleware({ request }, next) {
console.log(request.method, request.url);
await next();
- console.log(response.status, request.method, request.url);
+ console.log(`Finished ${request.method} ${request.url}`);
}
// Framework mode
@@ -720,6 +736,10 @@ export async function loader({
[common-patterns]: #common-patterns
[server-client]: #server-vs-client-middleware
[rr-config]: ../api/framework-conventions/react-router.config.ts
+[create-browser-router]: ../api/data-routers/createBrowserRouter
+[create-hash-router]: ../api/data-routers/createHashRouter
+[create-memory-router]: ../api/data-routers/createMemoryRouter
+[create-static-handler]: ../api/data-routers/createStaticHandler
[framework-action]: ../start/framework/route-module#action
[framework-loader]: ../start/framework/route-module#loader
[getloadcontext]: #changes-to-getloadcontextapploadcontext
diff --git a/docs/upgrading/future.md b/docs/upgrading/future.md
index 71c265bf83..5eaeefcdab 100644
--- a/docs/upgrading/future.md
+++ b/docs/upgrading/future.md
@@ -21,7 +21,7 @@ npm install react-router@7 @react-router/{dev,node,etc.}@7
## `future.v8_middleware`
-[MODES: framework]
+[MODES: framework, data]
@@ -32,6 +32,8 @@ Middleware allows you to run code before and after the [`Response`][Response] ge
👉 **Enable the Flag**
+In Framework mode:
+
```ts filename=react-router.config.ts
import type { Config } from "@react-router/dev/config";
@@ -42,11 +44,24 @@ export default {
} satisfies Config;
```
+In Data mode:
+
+```ts
+import { createBrowserRouter } from "react-router/dom";
+
+const router = createBrowserRouter(routes, {
+ future: {
+ v8_middleware: true,
+ },
+});
+```
+
**Update your Code**
-If you're using `react-router-serve`, then you should not need to make any updates to your code.
+If you're using the `context` parameter in `loader` and `action` functions, you may need to update your code:
-You should only need to update your code if you are using the `context` parameter in `loader` and `action` functions. This only applies if you have a custom server with a `getLoadContext` function. Please see the docs on the middleware [`getLoadContext` changes](../how-to/middleware#changes-to-getloadcontextapploadcontext) and the instructions to [migrate to the new API](../how-to/middleware#migration-from-apploadcontext).
+- In Framework mode, if you're using `react-router-serve`, you should not need to make any updates. Otherwise, this only applies if you have a custom server with a `getLoadContext` function. Please see the docs on the middleware [`getLoadContext` changes](../how-to/middleware#changes-to-getloadcontextapploadcontext) and the instructions to [migrate to the new API](../how-to/middleware#migration-from-apploadcontext).
+- In Data mode, add the `Future` module augmentation described in the [middleware docs](../how-to/middleware#2-typescript-augment-future-for-loaderaction-context) so `context` is typed correctly.
## `future.v8_splitRouteModules`