react-router 7.16.0 → 7.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/development/{browser-nIQ4Nsyi.d.mts → browser-CGcs-0pD.d.mts} +1 -1
  3. package/dist/development/{chunk-QUQL4437.mjs → chunk-6CSD65Y2.mjs} +2 -2
  4. package/dist/{production/chunk-NALGHHKE.mjs → development/chunk-ASILSGTR.mjs} +2 -2
  5. package/dist/development/{chunk-SRID2YZ2.js → chunk-KFNXW4AL.js} +1 -1
  6. package/dist/development/{chunk-XEJDWL2B.js → chunk-PBLBZ3QU.js} +7 -7
  7. package/dist/{production/chunk-SKEDDLRM.js → development/chunk-PULC7NLK.js} +99 -99
  8. package/dist/development/{context-m8rizgnE.d.mts → context-CmHpk1Ws.d.mts} +1 -1
  9. package/dist/development/dom-export.d.mts +3 -3
  10. package/dist/development/dom-export.d.ts +1 -1
  11. package/dist/development/dom-export.js +28 -28
  12. package/dist/development/dom-export.mjs +3 -3
  13. package/dist/development/{index-react-server-client-BLiUx67a.d.ts → index-react-server-client-CwU9bE5R.d.ts} +1 -1
  14. package/dist/development/{index-react-server-client-CdKROblb.d.mts → index-react-server-client-DPrDrCew.d.mts} +1 -1
  15. package/dist/development/index-react-server-client.d.mts +2 -2
  16. package/dist/development/index-react-server-client.d.ts +1 -1
  17. package/dist/development/index-react-server-client.js +4 -4
  18. package/dist/development/index-react-server-client.mjs +2 -2
  19. package/dist/development/index-react-server.js +1 -1
  20. package/dist/development/index-react-server.mjs +1 -1
  21. package/dist/development/index.d.mts +6 -6
  22. package/dist/development/index.d.ts +2 -2
  23. package/dist/development/index.js +85 -85
  24. package/dist/development/index.mjs +3 -3
  25. package/dist/development/lib/types/internal.js +1 -1
  26. package/dist/development/lib/types/internal.mjs +1 -1
  27. package/dist/production/{browser-nIQ4Nsyi.d.mts → browser-CGcs-0pD.d.mts} +1 -1
  28. package/dist/{development/chunk-S54KXAEJ.mjs → production/chunk-5TQZEVD5.mjs} +2 -2
  29. package/dist/production/{chunk-EAQNHM3N.js → chunk-CTIXC7EV.js} +7 -7
  30. package/dist/{development/chunk-IBI7OMNB.js → production/chunk-EN242BO4.js} +99 -99
  31. package/dist/production/{chunk-Q65P7S7Y.mjs → chunk-OSYEOCBT.mjs} +2 -2
  32. package/dist/production/{chunk-Y7DNFQZP.js → chunk-RTRY3JFT.js} +1 -1
  33. package/dist/production/{context-m8rizgnE.d.mts → context-CmHpk1Ws.d.mts} +1 -1
  34. package/dist/production/dom-export.d.mts +3 -3
  35. package/dist/production/dom-export.d.ts +1 -1
  36. package/dist/production/dom-export.js +28 -28
  37. package/dist/production/dom-export.mjs +3 -3
  38. package/dist/production/{index-react-server-client-BLiUx67a.d.ts → index-react-server-client-CwU9bE5R.d.ts} +1 -1
  39. package/dist/production/{index-react-server-client-CdKROblb.d.mts → index-react-server-client-DPrDrCew.d.mts} +1 -1
  40. package/dist/production/index-react-server-client.d.mts +2 -2
  41. package/dist/production/index-react-server-client.d.ts +1 -1
  42. package/dist/production/index-react-server-client.js +4 -4
  43. package/dist/production/index-react-server-client.mjs +2 -2
  44. package/dist/production/index-react-server.js +1 -1
  45. package/dist/production/index-react-server.mjs +1 -1
  46. package/dist/production/index.d.mts +6 -6
  47. package/dist/production/index.d.ts +2 -2
  48. package/dist/production/index.js +85 -85
  49. package/dist/production/index.mjs +3 -3
  50. package/dist/production/lib/types/internal.js +1 -1
  51. package/dist/production/lib/types/internal.mjs +1 -1
  52. package/docs/explanation/backend-for-frontend.md +50 -0
  53. package/docs/explanation/code-splitting.md +61 -0
  54. package/docs/explanation/concurrency.md +135 -0
  55. package/docs/explanation/form-vs-fetcher.md +292 -0
  56. package/docs/explanation/hot-module-replacement.md +137 -0
  57. package/docs/explanation/hydration.md +14 -0
  58. package/docs/explanation/index-query-param.md +86 -0
  59. package/docs/explanation/index.md +4 -0
  60. package/docs/explanation/lazy-route-discovery.md +78 -0
  61. package/docs/explanation/location.md +6 -0
  62. package/docs/explanation/progressive-enhancement.md +150 -0
  63. package/docs/explanation/race-conditions.md +88 -0
  64. package/docs/explanation/react-transitions.md +160 -0
  65. package/docs/explanation/route-matching.md +7 -0
  66. package/docs/explanation/server-client-execution.md +4 -0
  67. package/docs/explanation/sessions-and-cookies.md +465 -0
  68. package/docs/explanation/special-files.md +16 -0
  69. package/docs/explanation/state-management.md +524 -0
  70. package/docs/explanation/styling.md +87 -0
  71. package/docs/explanation/type-safety.md +82 -0
  72. package/docs/how-to/accessibility.md +44 -0
  73. package/docs/how-to/client-data.md +199 -0
  74. package/docs/how-to/data-strategy.md +317 -0
  75. package/docs/how-to/error-boundary.md +231 -0
  76. package/docs/how-to/error-reporting.md +142 -0
  77. package/docs/how-to/fetchers.md +307 -0
  78. package/docs/how-to/file-route-conventions.md +410 -0
  79. package/docs/how-to/file-uploads.md +217 -0
  80. package/docs/how-to/form-validation.md +120 -0
  81. package/docs/how-to/headers.md +164 -0
  82. package/docs/how-to/index.md +4 -0
  83. package/docs/how-to/instrumentation.md +556 -0
  84. package/docs/how-to/meta.md +40 -0
  85. package/docs/how-to/middleware.md +763 -0
  86. package/docs/how-to/navigation-blocking.md +233 -0
  87. package/docs/how-to/optimize-revalidation.md +12 -0
  88. package/docs/how-to/pre-rendering.md +225 -0
  89. package/docs/how-to/presets.md +103 -0
  90. package/docs/how-to/react-server-components.md +899 -0
  91. package/docs/how-to/resource-routes.md +126 -0
  92. package/docs/how-to/route-module-type-safety.md +100 -0
  93. package/docs/how-to/search-params.md +4 -0
  94. package/docs/how-to/security.md +30 -0
  95. package/docs/how-to/server-bundles.md +66 -0
  96. package/docs/how-to/spa.md +120 -0
  97. package/docs/how-to/status.md +63 -0
  98. package/docs/how-to/suspense.md +132 -0
  99. package/docs/how-to/using-handle.md +117 -0
  100. package/docs/how-to/view-transitions.md +237 -0
  101. package/docs/how-to/webhook.md +50 -0
  102. package/docs/index.md +39 -0
  103. package/docs/start/data/actions.md +138 -0
  104. package/docs/start/data/custom.md +198 -0
  105. package/docs/start/data/data-loading.md +44 -0
  106. package/docs/start/data/index.md +4 -0
  107. package/docs/start/data/installation.md +52 -0
  108. package/docs/start/data/navigating.md +12 -0
  109. package/docs/start/data/pending-ui.md +12 -0
  110. package/docs/start/data/route-object.md +268 -0
  111. package/docs/start/data/routing.md +281 -0
  112. package/docs/start/data/testing.md +8 -0
  113. package/docs/start/declarative/index.md +4 -0
  114. package/docs/start/declarative/installation.md +43 -0
  115. package/docs/start/declarative/navigating.md +133 -0
  116. package/docs/start/declarative/routing.md +237 -0
  117. package/docs/start/declarative/url-values.md +65 -0
  118. package/docs/start/framework/actions.md +174 -0
  119. package/docs/start/framework/data-loading.md +201 -0
  120. package/docs/start/framework/deploying.md +96 -0
  121. package/docs/start/framework/index.md +4 -0
  122. package/docs/start/framework/installation.md +41 -0
  123. package/docs/start/framework/navigating.md +182 -0
  124. package/docs/start/framework/pending-ui.md +142 -0
  125. package/docs/start/framework/rendering.md +59 -0
  126. package/docs/start/framework/route-module.md +527 -0
  127. package/docs/start/framework/routing.md +362 -0
  128. package/docs/start/framework/testing.md +133 -0
  129. package/docs/start/index.md +4 -0
  130. package/docs/start/modes.md +201 -0
  131. package/docs/upgrading/component-routes.md +363 -0
  132. package/docs/upgrading/future.md +280 -0
  133. package/docs/upgrading/index.md +4 -0
  134. package/docs/upgrading/remix.md +403 -0
  135. package/docs/upgrading/router-provider.md +442 -0
  136. package/docs/upgrading/v6.md +382 -0
  137. package/package.json +2 -1
@@ -0,0 +1,198 @@
1
+ ---
2
+ title: Custom Framework
3
+ order: 8
4
+ ---
5
+
6
+ # Custom Framework
7
+
8
+ [MODES: data]
9
+
10
+ ## Introduction
11
+
12
+ Instead of using `@react-router/dev`, you can integrate React Router's framework features (like loaders, actions, fetchers, etc.) into your own bundler and server abstractions with Data Mode.
13
+
14
+ ## Client Rendering
15
+
16
+ ### 1. Create a Router
17
+
18
+ The browser runtime API that enables route module APIs (loaders, actions, etc.) is `createBrowserRouter`.
19
+
20
+ It takes an array of route objects that support loaders, actions, error boundaries and more. The React Router Vite plugin creates one of these from `routes.ts`, but you can create one manually (or with an abstraction) and use your own bundler.
21
+
22
+ ```tsx
23
+ import { createBrowserRouter } from "react-router";
24
+
25
+ let router = createBrowserRouter([
26
+ {
27
+ path: "/",
28
+ Component: Root,
29
+ children: [
30
+ {
31
+ path: "shows/:showId",
32
+ Component: Show,
33
+ loader: ({ request, params }) =>
34
+ fetch(`/api/show/${params.showId}.json`, {
35
+ signal: request.signal,
36
+ }),
37
+ },
38
+ ],
39
+ },
40
+ ]);
41
+ ```
42
+
43
+ ### 2. Render the Router
44
+
45
+ To render the router in the browser, use `<RouterProvider>`.
46
+
47
+ ```tsx
48
+ import {
49
+ createBrowserRouter,
50
+ RouterProvider,
51
+ } from "react-router";
52
+ import { createRoot } from "react-dom/client";
53
+
54
+ createRoot(document.getElementById("root")).render(
55
+ <RouterProvider router={router} />,
56
+ );
57
+ ```
58
+
59
+ ### 3. Lazy Loading
60
+
61
+ Routes can take most of their definition lazily with the `lazy` property.
62
+
63
+ ```tsx
64
+ createBrowserRouter([
65
+ {
66
+ path: "/show/:showId",
67
+ lazy: {
68
+ loader: async () =>
69
+ (await import("./show.loader.js")).loader,
70
+ action: async () =>
71
+ (await import("./show.action.js")).action,
72
+ Component: async () =>
73
+ (await import("./show.component.js")).Component,
74
+ },
75
+ },
76
+ ]);
77
+ ```
78
+
79
+ ## Server Rendering
80
+
81
+ To server render a custom setup, there are a few server APIs available for rendering and data loading.
82
+
83
+ This guide simply gives you some ideas about how it works. For deeper understanding, please see the [Custom Framework Example Repo](https://github.com/remix-run/custom-react-router-framework-example)
84
+
85
+ ### 1. Define Your Routes
86
+
87
+ Routes are the same kinds of objects on the server as the client.
88
+
89
+ ```tsx
90
+ export default [
91
+ {
92
+ path: "/",
93
+ Component: Root,
94
+ children: [
95
+ {
96
+ path: "shows/:showId",
97
+ Component: Show,
98
+ loader: ({ params }) => {
99
+ return db.loadShow(params.id);
100
+ },
101
+ },
102
+ ],
103
+ },
104
+ ];
105
+ ```
106
+
107
+ ### 2. Create a static handler
108
+
109
+ Turn your routes into a request handler with `createStaticHandler`:
110
+
111
+ ```tsx
112
+ import { createStaticHandler } from "react-router";
113
+ import routes from "./some-routes";
114
+
115
+ let { query, dataRoutes } = createStaticHandler(routes);
116
+ ```
117
+
118
+ ### 3. Get Routing Context and Render
119
+
120
+ React Router works with web fetch [Requests](https://developer.mozilla.org/en-US/docs/Web/API/Request), so if your server doesn't, you'll need to adapt whatever objects it uses to a web fetch `Request` object.
121
+
122
+ This step assumes your server receives `Request` objects.
123
+
124
+ ```tsx
125
+ import { renderToString } from "react-dom/server";
126
+ import {
127
+ createStaticHandler,
128
+ createStaticRouter,
129
+ StaticRouterProvider,
130
+ } from "react-router";
131
+
132
+ import routes from "./some-routes.js";
133
+
134
+ let { query, dataRoutes } = createStaticHandler(routes);
135
+
136
+ export async function handler(request: Request) {
137
+ // 1. run actions/loaders to get the routing context with `query`
138
+ let context = await query(request);
139
+
140
+ // If `query` returns a Response, send it raw (a route probably a redirected)
141
+ if (context instanceof Response) {
142
+ return context;
143
+ }
144
+
145
+ // 2. Create a static router for SSR
146
+ let router = createStaticRouter(dataRoutes, context);
147
+
148
+ // 3. Render everything with StaticRouterProvider
149
+ let html = renderToString(
150
+ <StaticRouterProvider
151
+ router={router}
152
+ context={context}
153
+ />,
154
+ );
155
+
156
+ // Setup headers from action and loaders from deepest match
157
+ let leaf = context.matches[context.matches.length - 1];
158
+ let actionHeaders = context.actionHeaders[leaf.route.id];
159
+ let loaderHeaders = context.loaderHeaders[leaf.route.id];
160
+ let headers = new Headers(actionHeaders);
161
+ if (loaderHeaders) {
162
+ for (let [key, value] of loaderHeaders.entries()) {
163
+ headers.append(key, value);
164
+ }
165
+ }
166
+
167
+ headers.set("Content-Type", "text/html; charset=utf-8");
168
+
169
+ // 4. send a response
170
+ return new Response(`<!DOCTYPE html>${html}`, {
171
+ status: context.statusCode,
172
+ headers,
173
+ });
174
+ }
175
+ ```
176
+
177
+ ### 4. Hydrate in the browser
178
+
179
+ Hydration data is embedded onto `window.__staticRouterHydrationData`, use that to initialize your client side router and render a `<RouterProvider>`.
180
+
181
+ ```tsx
182
+ import { StrictMode } from "react";
183
+ import { hydrateRoot } from "react-dom/client";
184
+ import { RouterProvider } from "react-router/dom";
185
+ import routes from "./app/routes.js";
186
+ import { createBrowserRouter } from "react-router";
187
+
188
+ let router = createBrowserRouter(routes, {
189
+ hydrationData: window.__staticRouterHydrationData,
190
+ });
191
+
192
+ hydrateRoot(
193
+ document,
194
+ <StrictMode>
195
+ <RouterProvider router={router} />
196
+ </StrictMode>,
197
+ );
198
+ ```
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: Data Loading
3
+ order: 4
4
+ ---
5
+
6
+ # Data Loading
7
+
8
+ [MODES: data]
9
+
10
+ ## Providing Data
11
+
12
+ Data is provided to route components from route loaders:
13
+
14
+ ```tsx
15
+ createBrowserRouter([
16
+ {
17
+ path: "/",
18
+ loader: async () => {
19
+ // return data from here
20
+ return { records: await getSomeRecords() };
21
+ },
22
+ Component: MyRoute,
23
+ },
24
+ ]);
25
+ ```
26
+
27
+ ## Accessing Data
28
+
29
+ The data is available in route components with `useLoaderData`.
30
+
31
+ ```tsx
32
+ import { useLoaderData } from "react-router";
33
+
34
+ function MyRoute() {
35
+ const { records } = useLoaderData();
36
+ return <div>{records.length}</div>;
37
+ }
38
+ ```
39
+
40
+ As the user navigates between routes, the loaders are called before the route component is rendered.
41
+
42
+ ---
43
+
44
+ Next: [Actions](./actions)
@@ -0,0 +1,4 @@
1
+ ---
2
+ title: Data Mode
3
+ order: 3
4
+ ---
@@ -0,0 +1,52 @@
1
+ ---
2
+ title: Installation
3
+ order: 1
4
+ ---
5
+
6
+ # Installation
7
+
8
+ [MODES: data]
9
+
10
+ ## Bootstrap with a Bundler Template
11
+
12
+ You can start with a React template from Vite and choose "React", otherwise bootstrap your application however you prefer (Parcel, Webpack, etc).
13
+
14
+ ```shellscript nonumber
15
+ npx create-vite@latest
16
+ ```
17
+
18
+ ## Install React Router
19
+
20
+ Next install React Router from npm:
21
+
22
+ ```shellscript nonumber
23
+ npm i react-router
24
+ ```
25
+
26
+ ## Create a Router and Render
27
+
28
+ Create a router and pass it to `RouterProvider`:
29
+
30
+ ```tsx lines=[3-4,6-11,16]
31
+ import React from "react";
32
+ import ReactDOM from "react-dom/client";
33
+ import { createBrowserRouter } from "react-router";
34
+ import { RouterProvider } from "react-router/dom";
35
+
36
+ const router = createBrowserRouter([
37
+ {
38
+ path: "/",
39
+ element: <div>Hello World</div>,
40
+ },
41
+ ]);
42
+
43
+ const root = document.getElementById("root");
44
+
45
+ ReactDOM.createRoot(root).render(
46
+ <RouterProvider router={router} />,
47
+ );
48
+ ```
49
+
50
+ ---
51
+
52
+ Next: [Routing](./routing)
@@ -0,0 +1,12 @@
1
+ ---
2
+ title: Navigating
3
+ order: 6
4
+ ---
5
+
6
+ # Navigating
7
+
8
+ Navigating in Data Mode is the same as Framework Mode, please see the [Navigating](../framework/navigating) guide for more information.
9
+
10
+ ---
11
+
12
+ Next: [Pending UI](./pending-ui)
@@ -0,0 +1,12 @@
1
+ ---
2
+ title: Pending UI
3
+ order: 7
4
+ ---
5
+
6
+ # Pending UI
7
+
8
+ Pending UI is the same as Framework Mode, please see the [Pending UI](../framework/pending-ui) guide for more information.
9
+
10
+ ---
11
+
12
+ Next: [Custom Framework](./custom)
@@ -0,0 +1,268 @@
1
+ ---
2
+ title: Route Object
3
+ order: 3
4
+ ---
5
+
6
+ # Route Object
7
+
8
+ [MODES: data]
9
+
10
+ ## Introduction
11
+
12
+ The objects passed to `createBrowserRouter` are called Route Objects.
13
+
14
+ ```tsx lines=[2-5]
15
+ createBrowserRouter([
16
+ {
17
+ path: "/",
18
+ Component: App,
19
+ },
20
+ ]);
21
+ ```
22
+
23
+ Route modules are the foundation of React Router's data features, they define:
24
+
25
+ - data loading
26
+ - actions
27
+ - revalidation
28
+ - error boundaries
29
+ - and more
30
+
31
+ This guide is a quick overview of every route object feature.
32
+
33
+ ## Component
34
+
35
+ The `Component` property in a route object defines the component that will render when the route matches.
36
+
37
+ ```tsx lines=[4]
38
+ createBrowserRouter([
39
+ {
40
+ path: "/",
41
+ Component: MyRouteComponent,
42
+ },
43
+ ]);
44
+
45
+ function MyRouteComponent() {
46
+ return (
47
+ <div>
48
+ <h1>Look ma!</h1>
49
+ <p>
50
+ I'm still using React Router after like 10 years.
51
+ </p>
52
+ </div>
53
+ );
54
+ }
55
+ ```
56
+
57
+ ## `middleware`
58
+
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.
60
+
61
+ ```tsx
62
+ createBrowserRouter([
63
+ {
64
+ path: "/",
65
+ middleware: [loggingMiddleware],
66
+ loader: rootLoader,
67
+ Component: Root,
68
+ children: [{
69
+ path: 'auth',
70
+ middleware: [authMiddleware],
71
+ loader: authLoader,
72
+ Component: Auth,
73
+ children: [...]
74
+ }]
75
+ },
76
+ ]);
77
+
78
+ async function loggingMiddleware({ request }, next) {
79
+ let url = new URL(request.url);
80
+ console.log(`Starting navigation: ${url.pathname}${url.search}`);
81
+ const start = performance.now();
82
+ await next();
83
+ const duration = performance.now() - start;
84
+ console.log(`Navigation completed in ${duration}ms`);
85
+ }
86
+
87
+ const userContext = createContext<User>();
88
+
89
+ async function authMiddleware ({ context }) {
90
+ const userId = getUserId();
91
+
92
+ if (!userId) {
93
+ throw redirect("/login");
94
+ }
95
+
96
+ context.set(userContext, await getUserById(userId));
97
+ };
98
+ ```
99
+
100
+ See also:
101
+
102
+ - [Middleware][middleware]
103
+
104
+ ## `loader`
105
+
106
+ Route loaders provide data to route components before they are rendered.
107
+
108
+ ```tsx
109
+ import {
110
+ useLoaderData,
111
+ createBrowserRouter,
112
+ } from "react-router";
113
+
114
+ createBrowserRouter([
115
+ {
116
+ path: "/",
117
+ loader: loader,
118
+ Component: MyRoute,
119
+ },
120
+ ]);
121
+
122
+ async function loader({ params }) {
123
+ return { message: "Hello, world!" };
124
+ }
125
+
126
+ function MyRoute() {
127
+ let data = useLoaderData();
128
+ return <h1>{data.message}</h1>;
129
+ }
130
+ ```
131
+
132
+ See also:
133
+
134
+ - [`loader` params][loader-params]
135
+
136
+ ## `action`
137
+
138
+ Route actions allow server-side data mutations with automatic revalidation of all loader data on the page when called from `<Form>`, `useFetcher`, and `useSubmit`.
139
+
140
+ ```tsx
141
+ import {
142
+ createBrowserRouter,
143
+ useLoaderData,
144
+ useActionData,
145
+ Form,
146
+ } from "react-router";
147
+ import { TodoList } from "~/components/TodoList";
148
+
149
+ createBrowserRouter([
150
+ {
151
+ path: "/items",
152
+ action: action,
153
+ loader: loader,
154
+ Component: Items,
155
+ },
156
+ ]);
157
+
158
+ async function action({ request }) {
159
+ const data = await request.formData();
160
+ const todo = await fakeDb.addItem({
161
+ title: data.get("title"),
162
+ });
163
+ return { ok: true };
164
+ }
165
+
166
+ // this data will be revalidated after the action completes...
167
+ async function loader() {
168
+ const items = await fakeDb.getItems();
169
+ return { items };
170
+ }
171
+
172
+ // ...so that the list here is updated automatically
173
+ export default function Items() {
174
+ let data = useLoaderData();
175
+ return (
176
+ <div>
177
+ <List items={data.items} />
178
+ <Form method="post" navigate={false}>
179
+ <input type="text" name="title" />
180
+ <button type="submit">Create Todo</button>
181
+ </Form>
182
+ </div>
183
+ );
184
+ }
185
+ ```
186
+
187
+ ## `shouldRevalidate`
188
+
189
+ Loader data is automatically revalidated after certain events like navigations and form submissions.
190
+
191
+ This hook enables you to opt in or out of the default revalidation behavior. The default behavior is nuanced to avoid calling loaders unnecessarily.
192
+
193
+ A route loader is revalidated when:
194
+
195
+ - its own route params change
196
+ - any change to URL search params
197
+ - after an action is called and returns a non-error status code
198
+
199
+ By defining this function, you opt out of the default behavior completely and can manually control when loader data is revalidated for navigations and form submissions.
200
+
201
+ ```tsx
202
+ import type { ShouldRevalidateFunctionArgs } from "react-router";
203
+
204
+ function shouldRevalidate(
205
+ arg: ShouldRevalidateFunctionArgs,
206
+ ) {
207
+ return true; // false
208
+ }
209
+
210
+ createBrowserRouter([
211
+ {
212
+ path: "/",
213
+ shouldRevalidate: shouldRevalidate,
214
+ Component: MyRoute,
215
+ },
216
+ ]);
217
+ ```
218
+
219
+ [`ShouldRevalidateFunctionArgs` Reference Documentation ↗](https://api.reactrouter.com/v7/interfaces/react-router.ShouldRevalidateFunctionArgs.html)
220
+
221
+ Please note the default behavior is different in [Framework Mode](../modes).
222
+
223
+ ## `lazy`
224
+
225
+ Most properties can be lazily imported to reduce the initial bundle size.
226
+
227
+ ```tsx
228
+ createBrowserRouter([
229
+ {
230
+ path: "/app",
231
+ lazy: async () => {
232
+ // load component and loader in parallel before rendering
233
+ const [Component, loader] = await Promise.all([
234
+ import("./app"),
235
+ import("./app-loader"),
236
+ ]);
237
+ return { Component, loader };
238
+ },
239
+ },
240
+ ]);
241
+ ```
242
+
243
+ ## `handle`
244
+
245
+ Route handle allows apps to add anything to a route match in `useMatches` to create abstractions (like breadcrumbs, etc.).
246
+
247
+ ```tsx
248
+ createBrowserRouter([
249
+ {
250
+ path: "/app",
251
+ handle: {
252
+ breadcrumb: "App",
253
+ },
254
+ },
255
+ ]);
256
+ ```
257
+
258
+ See also:
259
+
260
+ - [`useMatches`][use-matches]
261
+
262
+ ---
263
+
264
+ Next: [Data Loading](./data-loading)
265
+
266
+ [loader-params]: https://api.reactrouter.com/v7/interfaces/react-router.LoaderFunctionArgs
267
+ [middleware]: ../../how-to/middleware
268
+ [use-matches]: ../../api/hooks/useMatches