or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-loading-hooks.mdindex.mdnavigation-components.mdnavigation-hooks.mdroute-configuration.mdrouter-components.mdrouter-creation.mdserver-side-rendering.mdutilities.md

router-creation.mddocs/

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

```