UNPKG

6.2 kB Markdown View Raw
1---
2title: Routing
3order: 2
4---
5
6# Routing
7
8[MODES: data]
9
10## Configuring Routes
11
12Routes are configured as the first argument to `createBrowserRouter`. At a minimum, you need a path and component:
13
14```tsx
15import { createBrowserRouter } from "react-router";
16
17function Root() {
18 return <h1>Hello world</h1>;
19}
20
21const router = createBrowserRouter([
22 { path: "/", Component: Root },
23]);
24```
25
26Here is a larger sample route config:
27
28```ts filename=app/routes.ts
29createBrowserRouter([
30 {
31 path: "/",
32 Component: Root,
33 children: [
34 { index: true, Component: Home },
35 { path: "about", Component: About },
36 {
37 path: "auth",
38 Component: AuthLayout,
39 children: [
40 { path: "login", Component: Login },
41 { path: "register", Component: Register },
42 ],
43 },
44 {
45 path: "concerts",
46 children: [
47 { index: true, Component: ConcertsHome },
48 { path: ":city", Component: ConcertsCity },
49 { path: "trending", Component: ConcertsTrending },
50 ],
51 },
52 ],
53 },
54]);
55```
56
57## Route Objects
58
59Route objects define the behavior of a route beyond just the path and component, like data loading and actions. We'll go into more detail in the [Route Object guide](./route-object), but here's a quick example of a loader.
60
61```tsx filename=app/team.tsx
62import {
63 createBrowserRouter,
64 useLoaderData,
65} from "react-router";
66
67createBrowserRouter([
68 {
69 path: "/teams/:teamId",
70 loader: async ({ params }) => {
71 let team = await fetchTeam(params.teamId);
72 return { name: team.name };
73 },
74 Component: Team,
75 },
76]);
77
78function Team() {
79 let data = useLoaderData();
80 return <h1>{data.name}</h1>;
81}
82```
83
84## Nested Routes
85
86Routes can be nested inside parent routes through `children`.
87
88```ts filename=app/routes.ts
89createBrowserRouter([
90 {
91 path: "/dashboard",
92 Component: Dashboard,
93 children: [
94 { index: true, Component: Home },
95 { path: "settings", Component: Settings },
96 ],
97 },
98]);
99```
100
101The path of the parent is automatically included in the child, so this config creates both `"/dashboard"` and `"/dashboard/settings"` URLs.
102
103Child routes are rendered through the `<Outlet/>` in the parent route.
104
105```tsx filename=app/dashboard.tsx
106import { Outlet } from "react-router";
107
108export default function Dashboard() {
109 return (
110 <div>
111 <h1>Dashboard</h1>
112 {/* will either be <Home> or <Settings> */}
113 <Outlet />
114 </div>
115 );
116}
117```
118
119## Layout Routes
120
121Omitting the `path` in a route creates new [Nested Routes](#nested-routes) for its children without adding any segments to the URL.
122
123```tsx lines=[3,16]
124createBrowserRouter([
125 {
126 // no path on this parent route, just the component
127 Component: MarketingLayout,
128 children: [
129 { index: true, Component: Home },
130 { path: "contact", Component: Contact },
131 ],
132 },
133
134 {
135 path: "projects",
136 children: [
137 { index: true, Component: ProjectsHome },
138 {
139 // again, no path, just a component for the layout
140 Component: ProjectLayout,
141 children: [
142 { path: ":pid", Component: Project },
143 { path: ":pid/edit", Component: EditProject },
144 ],
145 },
146 ],
147 },
148]);
149```
150
151Note that:
152
153- `Home` and `Contact` will be rendered into the `MarketingLayout` outlet
154- `Project` and `EditProject` will be rendered into the `ProjectLayout` outlet while `ProjectsHome` will not.
155
156## Index Routes
157
158Index routes are defined by setting `index: true` on a route object without a path.
159
160```ts
161{ index: true, Component: Home }
162```
163
164Index routes render into their parent's [Outlet][outlet] at their parent's URL (like a default child route).
165
166```ts lines=[4,5,10,11]
167import { createBrowserRouter } from "react-router";
168
169createBrowserRouter([
170 // renders at "/"
171 { index: true, Component: Home },
172 {
173 Component: Dashboard,
174 path: "/dashboard",
175 children: [
176 // renders at "/dashboard"
177 { index: true, Component: DashboardHome },
178 { path: "settings", Component: DashboardSettings },
179 ],
180 },
181]);
182```
183
184Note that index routes can't have children.
185
186## Prefix Route
187
188A route with just a path and no component creates a group of routes with a path prefix.
189
190```tsx lines=[3]
191createBrowserRouter([
192 {
193 // no component, just a path
194 path: "/projects",
195 children: [
196 { index: true, Component: ProjectsHome },
197 { path: ":pid", Component: Project },
198 { path: ":pid/edit", Component: EditProject },
199 ],
200 },
201]);
202```
203
204This creates the routes `/projects`, `/projects/:pid`, and `/projects/:pid/edit` without introducing a layout component.
205
206## Dynamic Segments
207
208If a path segment starts with `:` then it becomes a "dynamic segment". When the route matches the URL, the dynamic segment will be parsed from the URL and provided as `params` to other router APIs.
209
210```ts lines=[2]
211{
212 path: "teams/:teamId",
213 loader: async ({ params }) => {
214 // params are available in loaders/actions
215 let team = await fetchTeam(params.teamId);
216 return { name: team.name };
217 },
218 Component: Team,
219}
220```
221
222```tsx
223import { useParams } from "react-router";
224
225function Team() {
226 // params are available in components through useParams
227 let params = useParams();
228 // ...
229}
230```
231
232You can have multiple dynamic segments in one route path:
233
234```ts
235{
236 path: "c/:categoryId/p/:productId";
237}
238```
239
240## Optional Segments
241
242You can make a route segment optional by adding a `?` to the end of the segment.
243
244```ts
245{
246 path: ":lang?/categories";
247}
248```
249
250You can have optional static segments, too:
251
252```ts
253{
254 path: "users/:userId/edit?";
255}
256```
257
258## Splats
259
260Also known as "catchall" and "star" segments. If a route path pattern ends with `/*` then it will match any characters following the `/`, including other `/` characters.
261
262```ts
263{
264 path: "files/*";
265 loader: async ({ params }) => {
266 params["*"]; // will contain the remaining URL after files/
267 };
268}
269```
270
271You can destructure the `*`, you just have to assign it a new name. A common name is `splat`:
272
273```tsx
274const { "*": splat } = params;
275```
276
277---
278
279Next: [Route Object](./route-object)
280
281[outlet]: https://api.reactrouter.com/v7/functions/react-router.Outlet.html