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

route-configuration.mddocs/

0

# Route Configuration

1

2

Route definition components and utilities for declaring application routes with support for nested routing, dynamic segments, and route data loading.

3

4

## Capabilities

5

6

### Routes

7

8

Container component that renders the first route that matches the current location.

9

10

```typescript { .api }

11

/**

12

* Container for Route components that renders the first matching route

13

* @param props - Routes configuration options

14

* @returns Route matching and rendering component

15

*/

16

function Routes(props: RoutesProps): JSX.Element;

17

18

interface RoutesProps {

19

/** Route components to match against */

20

children?: React.ReactNode;

21

/** Base location for relative matching */

22

location?: Partial<Location> | string;

23

}

24

```

25

26

**Usage Example:**

27

28

```tsx

29

import { Routes, Route } from "react-router-dom";

30

31

function App() {

32

return (

33

<Routes>

34

<Route path="/" element={<Home />} />

35

<Route path="/about" element={<About />} />

36

<Route path="/users/:id" element={<UserProfile />} />

37

</Routes>

38

);

39

}

40

```

41

42

### Route

43

44

Defines a single route with its path, component, and data loading configuration.

45

46

```typescript { .api }

47

/**

48

* Defines a route with path matching and element rendering

49

* @param props - Route configuration including path and element

50

* @returns Route definition for use within Routes

51

*/

52

function Route(props: RouteProps): JSX.Element;

53

54

interface RouteProps {

55

/** URL path pattern to match */

56

path?: string;

57

/** Indicates this is an index route (matches parent's path exactly) */

58

index?: boolean;

59

/** React element to render when route matches */

60

element?: React.ReactNode;

61

/** Error boundary element for this route */

62

errorElement?: React.ReactNode;

63

/** Data loader function */

64

loader?: LoaderFunction;

65

/** Form action handler */

66

action?: ActionFunction;

67

/** Nested route definitions */

68

children?: React.ReactNode;

69

/** Enable case-sensitive path matching */

70

caseSensitive?: boolean;

71

/** Function to determine if route data should revalidate */

72

shouldRevalidate?: ShouldRevalidateFunction;

73

/** Lazy route component loader */

74

lazy?: LazyRouteFunction;

75

}

76

77

type LoaderFunction = (args: LoaderFunctionArgs) =>

78

| Promise<Response>

79

| Response

80

| Promise<any>

81

| any;

82

83

type ActionFunction = (args: ActionFunctionArgs) =>

84

| Promise<Response>

85

| Response

86

| Promise<any>

87

| any;

88

89

interface LoaderFunctionArgs {

90

/** Request object with URL, headers, and body */

91

request: Request;

92

/** Route parameters extracted from URL */

93

params: Params;

94

/** Application context object */

95

context?: any;

96

}

97

98

interface ActionFunctionArgs {

99

/** Request object with form data and method */

100

request: Request;

101

/** Route parameters from URL */

102

params: Params;

103

/** Application context object */

104

context?: any;

105

}

106

107

type ShouldRevalidateFunction = (args: ShouldRevalidateFunctionArgs) => boolean;

108

109

interface ShouldRevalidateFunctionArgs {

110

currentUrl: URL;

111

currentParams: Params;

112

nextUrl: URL;

113

nextParams: Params;

114

formMethod?: string;

115

formAction?: string;

116

formEncType?: string;

117

formData?: FormData;

118

actionResult?: any;

119

}

120

```

121

122

**Usage Examples:**

123

124

```tsx

125

// Basic route

126

<Route path="/users" element={<Users />} />

127

128

// Route with parameters

129

<Route path="/users/:id" element={<UserProfile />} />

130

131

// Index route (matches parent exactly)

132

<Route index element={<Home />} />

133

134

// Route with data loading

135

<Route

136

path="/products/:id"

137

element={<Product />}

138

loader={async ({ params }) => {

139

return fetch(`/api/products/${params.id}`);

140

}}

141

/>

142

143

// Route with form action

144

<Route

145

path="/contact"

146

element={<ContactForm />}

147

action={async ({ request }) => {

148

const formData = await request.formData();

149

return await submitContact(formData);

150

}}

151

/>

152

153

// Nested routes

154

<Route path="/dashboard" element={<Dashboard />}>

155

<Route index element={<DashboardHome />} />

156

<Route path="settings" element={<Settings />} />

157

<Route path="profile" element={<Profile />} />

158

</Route>

159

```

160

161

### Outlet

162

163

Renders child routes in nested routing scenarios.

164

165

```typescript { .api }

166

/**

167

* Renders the matching child route component

168

* @param props - Outlet configuration options

169

* @returns Child route rendering component

170

*/

171

function Outlet(props: OutletProps): JSX.Element;

172

173

interface OutletProps {

174

/** Context data to pass to child routes */

175

context?: unknown;

176

}

177

```

178

179

**Usage Example:**

180

181

```tsx

182

// Parent component

183

function Dashboard() {

184

return (

185

<div>

186

<h1>Dashboard</h1>

187

<nav>

188

<Link to="stats">Statistics</Link>

189

<Link to="settings">Settings</Link>

190

</nav>

191

{/* Child routes render here */}

192

<Outlet />

193

</div>

194

);

195

}

196

197

// Route configuration

198

<Route path="/dashboard" element={<Dashboard />}>

199

<Route path="stats" element={<Statistics />} />

200

<Route path="settings" element={<Settings />} />

201

</Route>

202

```

203

204

### Await

205

206

Component for handling deferred data with Suspense and error boundaries.

207

208

```typescript { .api }

209

/**

210

* Component that resolves deferred data with Suspense support

211

* @param props - Await component configuration

212

* @returns Component that handles async data resolution

213

*/

214

function Await<T>(props: AwaitProps<T>): JSX.Element;

215

216

interface AwaitProps<T> {

217

/** Promise to resolve */

218

resolve: Promise<T>;

219

/** Component to render when promise resolves */

220

children: React.ReactNode | ((value: T) => React.ReactNode);

221

/** Component to render when promise rejects */

222

errorElement?: React.ReactNode | null;

223

}

224

```

225

226

**Usage Examples:**

227

228

```tsx

229

import { Await, useLoaderData, defer } from "react-router-dom";

230

import { Suspense } from "react";

231

232

// Loader that returns deferred data

233

export const userProfileLoader = async ({ params }) => {

234

// Fast data loaded immediately

235

const basicInfo = await fetch(`/api/users/${params.id}/basic`).then(r => r.json());

236

237

// Slow data deferred for streaming

238

const postsPromise = fetch(`/api/users/${params.id}/posts`).then(r => r.json());

239

const analyticsPromise = fetch(`/api/users/${params.id}/analytics`).then(r => r.json());

240

241

return defer({

242

basicInfo,

243

posts: postsPromise,

244

analytics: analyticsPromise

245

});

246

};

247

248

// Component using Await for deferred data

249

function UserProfile() {

250

const { basicInfo, posts, analytics } = useLoaderData<{

251

basicInfo: User;

252

posts: Promise<Post[]>;

253

analytics: Promise<Analytics>;

254

}>();

255

256

return (

257

<div>

258

{/* Immediate data */}

259

<h1>{basicInfo.name}</h1>

260

<p>{basicInfo.email}</p>

261

262

{/* Deferred data with loading states */}

263

<section>

264

<h2>Recent Posts</h2>

265

<Suspense fallback={<div>Loading posts...</div>}>

266

<Await resolve={posts}>

267

<PostsList />

268

</Await>

269

</Suspense>

270

</section>

271

272

<section>

273

<h2>Analytics</h2>

274

<Suspense fallback={<div>Loading analytics...</div>}>

275

<Await

276

resolve={analytics}

277

errorElement={<div>Failed to load analytics</div>}

278

>

279

<AnalyticsDashboard />

280

</Await>

281

</Suspense>

282

</section>

283

</div>

284

);

285

}

286

287

// Component that receives resolved data

288

function PostsList() {

289

const posts = useAsyncValue<Post[]>();

290

291

return (

292

<ul>

293

{posts.map(post => (

294

<li key={post.id}>

295

<h3>{post.title}</h3>

296

<p>{post.excerpt}</p>

297

</li>

298

))}

299

</ul>

300

);

301

}

302

303

// Component with error handling

304

function AnalyticsDashboard() {

305

const analytics = useAsyncValue<Analytics>();

306

307

return (

308

<div>

309

<p>Views: {analytics.views}</p>

310

<p>Engagement: {analytics.engagement}%</p>

311

</div>

312

);

313

}

314

315

// Error boundary for async errors

316

function AsyncErrorBoundary() {

317

const error = useAsyncError();

318

319

return (

320

<div className="error">

321

<h3>Something went wrong</h3>

322

<p>{error instanceof Error ? error.message : "Unknown error"}</p>

323

</div>

324

);

325

}

326

```

327

328

### Route Objects

329

330

Declarative route configuration objects for use with router creation functions.

331

332

```typescript { .api }

333

interface RouteObject {

334

/** URL path pattern to match */

335

path?: string;

336

/** Indicates this is an index route */

337

index?: boolean;

338

/** Nested route definitions */

339

children?: RouteObject[];

340

/** Enable case-sensitive matching */

341

caseSensitive?: boolean;

342

/** Unique route identifier */

343

id?: string;

344

/** Data loader function */

345

loader?: LoaderFunction;

346

/** Form action handler */

347

action?: ActionFunction;

348

/** Component to render */

349

element?: React.ReactNode | null;

350

/** Error boundary component */

351

errorElement?: React.ReactNode | null;

352

/** Revalidation control function */

353

shouldRevalidate?: ShouldRevalidateFunction;

354

/** Lazy component loader */

355

lazy?: LazyRouteFunction;

356

}

357

358

interface IndexRouteObject extends Omit<RouteObject, "path" | "children"> {

359

index: true;

360

}

361

362

interface NonIndexRouteObject extends RouteObject {

363

path: string;

364

index?: false;

365

}

366

367

interface DataRouteObject extends RouteObject {

368

/** Nested routes with data loading */

369

children?: DataRouteObject[];

370

/** Required unique identifier */

371

id: string;

372

}

373

374

type LazyRouteFunction<T extends RouteObject = RouteObject> = () => Promise<LazyRouteModule<T>>;

375

376

interface LazyRouteModule<T extends RouteObject = RouteObject> {

377

Component?: React.ComponentType<any> | null;

378

element?: React.ReactNode | null;

379

errorElement?: React.ReactNode | null;

380

loader?: T["loader"];

381

action?: T["action"];

382

shouldRevalidate?: T["shouldRevalidate"];

383

}

384

```

385

386

**Usage Example:**

387

388

```tsx

389

import { createBrowserRouter } from "react-router-dom";

390

391

const routes: RouteObject[] = [

392

{

393

path: "/",

394

element: <Root />,

395

errorElement: <ErrorBoundary />,

396

loader: rootLoader,

397

children: [

398

{

399

index: true,

400

element: <Home />,

401

},

402

{

403

path: "products/:id",

404

element: <Product />,

405

loader: productLoader,

406

action: productAction,

407

},

408

],

409

},

410

];

411

412

const router = createBrowserRouter(routes);

413

```

414

415

### Route Utilities

416

417

Functions for working with routes programmatically.

418

419

```typescript { .api }

420

/**

421

* Create route objects from JSX Route elements

422

* @param children - JSX Route elements

423

* @returns Array of RouteObject definitions

424

*/

425

function createRoutesFromElements(children: React.ReactNode): RouteObject[];

426

427

/** Alias for createRoutesFromElements */

428

function createRoutesFromChildren(children: React.ReactNode): RouteObject[];

429

430

/**

431

* Render matched routes as React elements

432

* @param matches - Route matches to render

433

* @param parentMatches - Parent route matches for context

434

* @returns Rendered route elements

435

*/

436

function renderMatches(

437

matches: RouteMatch[] | null,

438

parentMatches?: RouteMatch[]

439

): React.ReactElement | null;

440

441

interface RouteMatch<ParamKey extends string = string> {

442

/** Matched route parameters */

443

params: Params<ParamKey>;

444

/** Matched pathname */

445

pathname: string;

446

/** Pattern info used for matching */

447

pathnameBase: string;

448

/** Route definition */

449

route: RouteObject;

450

}

451

```

452

453

## Route Patterns

454

455

### Dynamic Segments

456

457

```tsx

458

// URL parameter

459

<Route path="/users/:userId" element={<User />} />

460

461

// Optional parameter

462

<Route path="/posts/:postId?" element={<Post />} />

463

464

// Multiple parameters

465

<Route path="/users/:userId/posts/:postId" element={<UserPost />} />

466

```

467

468

### Wildcard Routes

469

470

```tsx

471

// Catch-all route

472

<Route path="*" element={<NotFound />} />

473

474

// Splat routes (capture remaining path)

475

<Route path="/files/*" element={<FileBrowser />} />

476

```

477

478

### Index Routes

479

480

```tsx

481

// Renders at parent's exact path

482

<Route path="/dashboard" element={<Dashboard />}>

483

<Route index element={<DashboardHome />} />

484

<Route path="settings" element={<Settings />} />

485

</Route>

486

```