0
# Router Creation
1
2
Functions for creating router instances programmatically with support for data loading, static generation, and memory-based routing for testing.
3
4
## Capabilities
5
6
### createBrowserRouter
7
8
Creates a browser router instance with data loading capabilities.
9
10
```typescript { .api }
11
/**
12
* Creates a browser router with HTML5 history and data loading
13
* @param routes - Array of route definitions
14
* @param opts - Router configuration options
15
* @returns DataRouter instance with full feature support
16
*/
17
function createBrowserRouter(
18
routes: RouteObject[],
19
opts?: DOMRouterOpts
20
): DataRouter;
21
22
interface DOMRouterOpts {
23
/** Base URL for all routes */
24
basename?: string;
25
/** Custom data loading strategy */
26
unstable_dataStrategy?: DataStrategyFunction;
27
/** Dynamic route loading function */
28
unstable_patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction;
29
/** Future flags for experimental features */
30
future?: Partial<Future>;
31
/** Window object to use (for testing) */
32
window?: Window;
33
}
34
35
interface DataRouter {
36
/** Initialize the router and start listening */
37
initialize(): void;
38
/** Subscribe to router state changes */
39
subscribe(fn: RouterSubscriber): () => void;
40
/** Navigate programmatically */
41
navigate(to: To, opts?: RouterNavigateOptions): Promise<void>;
42
/** Fetch data for a route */
43
fetch(key: string, routeId: string, href: string, opts?: RouterFetchOptions): Promise<void>;
44
/** Trigger data revalidation */
45
revalidate(): void;
46
/** Get data for a specific route */
47
getRouteData(routeId: string): any;
48
/** Clean up and dispose router */
49
dispose(): void;
50
/** Current router state */
51
state: RouterState;
52
}
53
```
54
55
**Usage Examples:**
56
57
```tsx
58
import { createBrowserRouter, RouterProvider } from "react-router-dom";
59
60
// Basic router setup
61
const router = createBrowserRouter([
62
{
63
path: "/",
64
element: <Root />,
65
children: [
66
{
67
path: "dashboard",
68
element: <Dashboard />,
69
loader: async () => {
70
const response = await fetch("/api/dashboard");
71
return response.json();
72
},
73
},
74
{
75
path: "users/:id",
76
element: <User />,
77
loader: async ({ params }) => {
78
const response = await fetch(`/api/users/${params.id}`);
79
return response.json();
80
},
81
action: async ({ request, params }) => {
82
const formData = await request.formData();
83
const response = await fetch(`/api/users/${params.id}`, {
84
method: "PUT",
85
body: formData,
86
});
87
return response.json();
88
},
89
},
90
],
91
},
92
]);
93
94
function App() {
95
return <RouterProvider router={router} />;
96
}
97
98
// Router with options
99
const router = createBrowserRouter(routes, {
100
basename: "/my-app",
101
future: {
102
unstable_middleware: true,
103
},
104
});
105
```
106
107
### createHashRouter
108
109
Creates a hash-based router for compatibility with older browsers and static hosting.
110
111
```typescript { .api }
112
/**
113
* Creates a hash router for static hosting and legacy browser support
114
* @param routes - Array of route definitions
115
* @param opts - Router configuration options
116
* @returns DataRouter instance using hash-based routing
117
*/
118
function createHashRouter(
119
routes: RouteObject[],
120
opts?: DOMRouterOpts
121
): DataRouter;
122
```
123
124
**Usage Example:**
125
126
```tsx
127
import { createHashRouter, RouterProvider } from "react-router-dom";
128
129
const router = createHashRouter([
130
{
131
path: "/",
132
element: <Home />,
133
},
134
{
135
path: "/about",
136
element: <About />,
137
},
138
]);
139
140
// URLs will be: example.com#/ and example.com#/about
141
function App() {
142
return <RouterProvider router={router} />;
143
}
144
```
145
146
### createMemoryRouter
147
148
Creates an in-memory router perfect for testing and non-browser environments.
149
150
```typescript { .api }
151
/**
152
* Creates a memory router that stores history in memory
153
* @param routes - Array of route definitions
154
* @param opts - Memory router configuration options
155
* @returns DataRouter instance with in-memory history
156
*/
157
function createMemoryRouter(
158
routes: RouteObject[],
159
opts?: MemoryRouterOpts
160
): DataRouter;
161
162
interface MemoryRouterOpts {
163
/** Base URL for all routes */
164
basename?: string;
165
/** Custom data loading strategy */
166
unstable_dataStrategy?: DataStrategyFunction;
167
/** Dynamic route loading function */
168
unstable_patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction;
169
/** Future flags */
170
future?: Partial<Future>;
171
/** Initial location entries */
172
initialEntries?: InitialEntry[];
173
/** Initial index in history stack */
174
initialIndex?: number;
175
}
176
177
type InitialEntry = string | Partial<Location>;
178
```
179
180
**Usage Examples:**
181
182
```tsx
183
import { createMemoryRouter, RouterProvider } from "react-router-dom";
184
185
// Testing setup
186
const router = createMemoryRouter(
187
[
188
{
189
path: "/",
190
element: <Home />,
191
},
192
{
193
path: "/users/:id",
194
element: <User />,
195
loader: ({ params }) => ({ id: params.id, name: "John" }),
196
},
197
],
198
{
199
initialEntries: ["/", "/users/123"],
200
initialIndex: 1, // Start at /users/123
201
}
202
);
203
204
// Test component
205
function TestApp() {
206
return <RouterProvider router={router} />;
207
}
208
209
// React Native or Node.js usage
210
const serverRouter = createMemoryRouter(routes, {
211
initialEntries: [request.url],
212
});
213
```
214
215
### createStaticRouter
216
217
Creates a static router for server-side rendering.
218
219
```typescript { .api }
220
/**
221
* Creates a static router for server-side rendering
222
* @param routes - Array of route definitions
223
* @param location - Request location information
224
* @param opts - Static router options
225
* @returns DataRouter instance for SSR
226
*/
227
function createStaticRouter(
228
routes: RouteObject[],
229
location: Partial<Location> | string,
230
opts?: {
231
basename?: string;
232
future?: Partial<Future>;
233
}
234
): DataRouter;
235
```
236
237
**Usage Example:**
238
239
```tsx
240
import { createStaticRouter, StaticRouterProvider } from "react-router-dom";
241
242
// Server-side rendering
243
export async function render(request: Request) {
244
const router = createStaticRouter(routes, request.url);
245
246
const html = ReactDOMServer.renderToString(
247
<StaticRouterProvider router={router} context={{}} />
248
);
249
250
return new Response(html, {
251
headers: { "Content-Type": "text/html" },
252
});
253
}
254
```
255
256
### createStaticHandler
257
258
Creates a static handler for data loading in SSR environments.
259
260
```typescript { .api }
261
/**
262
* Creates a static handler for server-side data loading
263
* @param routes - Array of route definitions
264
* @param opts - Handler configuration options
265
* @returns StaticHandler for processing requests
266
*/
267
function createStaticHandler(
268
routes: RouteObject[],
269
opts?: {
270
basename?: string;
271
unstable_dataStrategy?: DataStrategyFunction;
272
}
273
): StaticHandler;
274
275
interface StaticHandler {
276
/** Handle a request and return data/redirect */
277
query(request: Request, opts?: {
278
requestContext?: unknown;
279
unstable_dataStrategy?: DataStrategyFunction;
280
}): Promise<StaticHandlerContext | Response>;
281
282
/** Handle a data request */
283
queryRoute(request: Request, opts?: {
284
routeId: string;
285
requestContext?: unknown;
286
}): Promise<any>;
287
}
288
289
interface StaticHandlerContext {
290
basename: string;
291
location: Location;
292
matches: StaticHandlerMatch[];
293
loaderData: Record<string, any>;
294
actionData: Record<string, any> | null;
295
errors: Record<string, any> | null;
296
statusCode: number;
297
loaderHeaders: Record<string, Headers>;
298
actionHeaders: Record<string, Headers> | null;
299
activeDeferreds: Record<string, DeferredData> | null;
300
}
301
```
302
303
**Usage Example:**
304
305
```tsx
306
import { createStaticHandler, createStaticRouter } from "react-router-dom";
307
308
// Server setup
309
const routes = [
310
{
311
path: "/",
312
element: <Home />,
313
loader: () => ({ message: "Welcome!" }),
314
},
315
{
316
path: "/users/:id",
317
element: <User />,
318
loader: async ({ params }) => {
319
const user = await fetchUser(params.id);
320
return { user };
321
},
322
},
323
];
324
325
export async function handleRequest(request: Request) {
326
const handler = createStaticHandler(routes);
327
const context = await handler.query(request);
328
329
if (context instanceof Response) {
330
return context; // Redirect response
331
}
332
333
const router = createStaticRouter(routes, context.location);
334
335
const html = ReactDOMServer.renderToString(
336
<StaticRouterProvider router={router} context={context} />
337
);
338
339
return new Response(html, {
340
status: context.statusCode,
341
headers: { "Content-Type": "text/html" },
342
});
343
}
344
```
345
346
## Router Configuration Options
347
348
### Data Strategy
349
350
Custom data loading strategy for advanced use cases.
351
352
```typescript { .api }
353
type DataStrategyFunction = (args: DataStrategyFunctionArgs) => Promise<DataStrategyResult>;
354
355
interface DataStrategyFunctionArgs {
356
request: Request;
357
matches: DataStrategyMatch[];
358
}
359
360
interface DataStrategyMatch {
361
route: RouteObject;
362
params: Params;
363
shouldLoad: boolean;
364
resolve: (value: any) => void;
365
reject: (error: any) => void;
366
}
367
368
interface DataStrategyResult {
369
[routeId: string]: any;
370
}
371
```
372
373
### Dynamic Route Loading
374
375
Function for loading routes dynamically during navigation.
376
377
```typescript { .api }
378
type PatchRoutesOnNavigationFunction = (
379
args: PatchRoutesOnNavigationFunctionArgs
380
) => Promise<void> | void;
381
382
interface PatchRoutesOnNavigationFunctionArgs {
383
path: string;
384
matches: RouteMatch[];
385
patch: (routeId: string | null, children: RouteObject[]) => void;
386
}
387
```
388
389
### Future Flags
390
391
Configuration for experimental features.
392
393
```typescript { .api }
394
interface Future {
395
/** Enable middleware support */
396
unstable_middleware: boolean;
397
/** Enable lazy route discovery */
398
unstable_lazyRouteDiscovery: boolean;
399
/** Enable optimistic UI updates */
400
unstable_optimisticUI: boolean;
401
}
402
```
403
404
## Router Selection Guide
405
406
- **createBrowserRouter**: Modern web applications with clean URLs and data loading
407
- **createHashRouter**: Static hosting, legacy browsers, or when clean URLs aren't available
408
- **createMemoryRouter**: Testing, React Native, or server-side environments
409
- **createStaticRouter**: Server-side rendering with React frameworks
410
- **createStaticHandler**: Advanced SSR with custom data loading strategies
411
412
## Best Practices
413
414
### Route Definition
415
416
```tsx
417
// Organize routes hierarchically
418
const routes = [
419
{
420
path: "/",
421
element: <Root />,
422
errorElement: <ErrorBoundary />,
423
loader: rootLoader,
424
children: [
425
{ index: true, element: <Home /> },
426
{
427
path: "dashboard",
428
element: <Dashboard />,
429
loader: dashboardLoader,
430
children: [
431
{ path: "analytics", element: <Analytics /> },
432
{ path: "settings", element: <Settings /> },
433
],
434
},
435
],
436
},
437
];
438
```
439
440
### Error Handling
441
442
```tsx
443
// Add error boundaries at appropriate levels
444
const routes = [
445
{
446
path: "/",
447
element: <Root />,
448
errorElement: <RootErrorBoundary />,
449
children: [
450
{
451
path: "admin",
452
element: <Admin />,
453
errorElement: <AdminErrorBoundary />,
454
loader: adminLoader,
455
},
456
],
457
},
458
];
459
```
460
461
### Data Loading
462
463
```tsx
464
// Implement proper error handling in loaders
465
const userLoader = async ({ params }) => {
466
try {
467
const response = await fetch(`/api/users/${params.id}`);
468
if (!response.ok) {
469
throw new Response("User not found", { status: 404 });
470
}
471
return response.json();
472
} catch (error) {
473
throw new Response("Network error", { status: 500 });
474
}
475
};
476
```