Skip to content

Commit f46c83c

Browse files
committed
Merge branch 'main' into release-next
2 parents 6ff0bb3 + 5344e4b commit f46c83c

File tree

6 files changed

+125
-30
lines changed

6 files changed

+125
-30
lines changed

contributors.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@
338338
- ryanflorence
339339
- ryanhiebert
340340
- saengmotmi
341+
- SailorStat
341342
- samimsu
342343
- sanjai451
343344
- sanketshah19

docs/api/components/Routes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { Route, Routes } from "react-router";
3333
<Routes>
3434
<Route index element={<StepOne />} />
3535
<Route path="step-2" element={<StepTwo />} />
36-
<Route path="step-3" element={<StepThree />}>
36+
<Route path="step-3" element={<StepThree />} />
3737
</Routes>
3838
```
3939

docs/how-to/middleware.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ export const middleware: Route.MiddlewareFunction[] = [
487487
];
488488
```
489489

490+
Which `ErrorBoundary` is rendered will differ based on whether your middleware threw _before_ or _after_ calling then `next()` function. If it throws _after_ then it will bubble up from the throwing route just like a normal loader error because we've already run the loaders and have the appropriate `loaderData` to render in the route components. However, if an error is thrown _before_ calling `next()`, then we haven't called any loaders yet and there is no `loaderData` available. When this happens, we must bubble up to the highest route with a `loader` and start looking for an `ErrorBoundary` there. We cannot render any route components at that level or below without any `loaderData`.
491+
490492
## Changes to `getLoadContext`/`AppLoadContext`
491493

492494
<docs-info>This only applies if you are using a custom server and a custom `getLoadContext` function</docs-info>

docs/how-to/using-handle.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
title: Using handle
3+
---
4+
5+
# Using `handle`
6+
7+
[MODES: framework]
8+
9+
<br/>
10+
<br/>
11+
12+
You can build dynamic UI elements like breadcrumbs based on your route hierarchy using the [`useMatches`][use-matches] hook and [`handle`][handle] route exports.
13+
14+
## Understanding the Basics
15+
16+
React Router provides access to all route matches and their data throughout your component tree. This allows routes to contribute metadata through the `handle` export that can be rendered by ancestor components.
17+
18+
The `useMatches` hook combined with `handle` exports enables routes to contribute to rendering processes higher up the component tree than their actual render point. While we'll use breadcrumbs as an example, this pattern works for any scenario where you need routes to provide additional information to their ancestors.
19+
20+
## Defining Route `handle`s
21+
22+
We'll use a route structure like the following:
23+
24+
```ts filename=app/routes.ts
25+
import { route } from "@react-router/dev/routes";
26+
27+
export default [
28+
route("parent", "./routes/parent.tsx", [
29+
route("child", "./routes/child.tsx"),
30+
]),
31+
] satisfies RouteConfig;
32+
```
33+
34+
Add a `breadcrumb` property to the "parent" route's `handle` export. You can name this property whatever makes sense for your use case.
35+
36+
```tsx filename=app/routes/parent.tsx
37+
import { Link } from "react-router";
38+
39+
export const handle = {
40+
breadcrumb: () => <Link to="/parent">Some Route</Link>,
41+
};
42+
```
43+
44+
You can define breadcrumbs for child routes as well:
45+
46+
```tsx filename=app/routes/child.tsx
47+
import { Link } from "react-router";
48+
49+
export const handle = {
50+
breadcrumb: () => (
51+
<Link to="/parent/child">Child Route</Link>
52+
),
53+
};
54+
```
55+
56+
## Using Route `handle`s
57+
58+
Use the `useMatches` hook in your root layout or any ancestor component to collect and render the components defined in the `handle` export(s):
59+
60+
```tsx filename=app/root.tsx lines=[7,11,22-31]
61+
import {
62+
Links,
63+
Meta,
64+
Outlet,
65+
Scripts,
66+
ScrollRestoration,
67+
useMatches,
68+
} from "react-router";
69+
70+
export function Layout({ children }) {
71+
const matches = useMatches();
72+
73+
return (
74+
<html lang="en">
75+
<head>
76+
<Meta />
77+
<Links />
78+
</head>
79+
<body>
80+
<header>
81+
<ol>
82+
{matches
83+
.filter(
84+
(match) =>
85+
match.handle && match.handle.breadcrumb,
86+
)
87+
.map((match, index) => (
88+
<li key={index}>
89+
{match.handle.breadcrumb(match)}
90+
</li>
91+
))}
92+
</ol>
93+
</header>
94+
{children}
95+
<ScrollRestoration />
96+
<Scripts />
97+
</body>
98+
</html>
99+
);
100+
}
101+
102+
export default function App() {
103+
return <Outlet />;
104+
}
105+
```
106+
107+
The `match` object is passed to each breadcrumb function, giving you access to `match.data` (from loaders) and other route information to create dynamic breadcrumbs based on your route's data.
108+
109+
This pattern provides a clean way for routes to contribute metadata that can be consumed and rendered by ancestor components.
110+
111+
## Additional Resources
112+
113+
- [`useMatches`][use-matches]
114+
- [`handle`][handle]
115+
116+
[use-matches]: ../api/hooks/useMatches
117+
[handle]: ../start/framework/route-module#handle

docs/start/framework/deploying.md

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -81,37 +81,12 @@ The containerized application can be deployed to any platform that supports Dock
8181

8282
### Vercel
8383

84-
```
85-
npx create-react-router@latest --template remix-run/react-router-templates/vercel
86-
```
87-
88-
- Server Rendering
89-
- Tailwind CSS
90-
91-
### Cloudflare Workers w/ D1
92-
93-
```
94-
npx create-react-router@latest --template remix-run/react-router-templates/cloudflare-d1
95-
```
96-
97-
- Server Rendering
98-
- D1 Database with Drizzle ORM
99-
- Tailwind CSS
84+
Vercel maintains their own template for React Router. Checkout the [Vercel Guide](https://vercel.com/templates/react-router/react-router-boilerplate) for more information.
10085

10186
### Cloudflare Workers
10287

103-
```
104-
npx create-react-router@latest --template remix-run/react-router-templates/cloudflare
105-
```
106-
107-
- Server Rendering
108-
- Tailwind CSS
88+
Cloudflare maintains their own template for React Router. Checkout the [Cloudflare Guide](https://developers.cloudflare.com/workers/framework-guides/web-apps/react-router/) for more information.
10989

11090
### Netlify
11191

112-
```
113-
npx create-react-router@latest --template remix-run/react-router-templates/netlify
114-
```
115-
116-
- Server Rendering
117-
- Tailwind CSS
92+
Netlify maintains their own template for React Router. Checkout the [Netlify Guide](https://docs.netlify.com/build/frameworks/framework-setup-guides/react-router/) for more information.

packages/react-router/lib/components.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,7 @@ export interface RoutesProps {
13581358
* <Routes>
13591359
* <Route index element={<StepOne />} />
13601360
* <Route path="step-2" element={<StepTwo />} />
1361-
* <Route path="step-3" element={<StepThree />}>
1361+
* <Route path="step-3" element={<StepThree />} />
13621362
* </Routes>
13631363
*
13641364
* @public

0 commit comments

Comments
 (0)