UNPKG

5.7 kB Markdown View Raw
1---
2title: Routing
3order: 2
4---
5
6# Routing
7
8[MODES: declarative]
9
10## Configuring Routes
11
12Routes are configured by rendering `<Routes>` and `<Route>` that couple URL segments to UI elements.
13
14```tsx
15import React from "react";
16import ReactDOM from "react-dom/client";
17import { BrowserRouter, Routes, Route } from "react-router";
18import App from "./app";
19
20const root = document.getElementById("root");
21
22ReactDOM.createRoot(root).render(
23 <BrowserRouter>
24 <Routes>
25 <Route path="/" element={<App />} />
26 </Routes>
27 </BrowserRouter>,
28);
29```
30
31Here's a larger sample config:
32
33```tsx
34<Routes>
35 <Route index element={<Home />} />
36 <Route path="about" element={<About />} />
37
38 <Route element={<AuthLayout />}>
39 <Route path="login" element={<Login />} />
40 <Route path="register" element={<Register />} />
41 </Route>
42
43 <Route path="concerts">
44 <Route index element={<ConcertsHome />} />
45 <Route path=":city" element={<City />} />
46 <Route path="trending" element={<Trending />} />
47 </Route>
48</Routes>
49```
50
51## Nested Routes
52
53Routes can be nested inside parent routes.
54
55```tsx
56<Routes>
57 <Route path="dashboard" element={<Dashboard />}>
58 <Route index element={<Home />} />
59 <Route path="settings" element={<Settings />} />
60 </Route>
61</Routes>
62```
63
64The path of the parent is automatically included in the child, so this config creates both `"/dashboard"` and `"/dashboard/settings"` URLs.
65
66Child routes are rendered through the `<Outlet/>` in the parent route.
67
68```tsx filename=app/dashboard.tsx
69import { Outlet } from "react-router";
70
71export default function Dashboard() {
72 return (
73 <div>
74 <h1>Dashboard</h1>
75 {/* will either be <Home/> or <Settings/> */}
76 <Outlet />
77 </div>
78 );
79}
80```
81
82## Layout Routes
83
84Routes _without_ a `path` create new nesting for their children, but they don't add any segments to the URL.
85
86```tsx lines=[2,9]
87<Routes>
88 <Route element={<MarketingLayout />}>
89 <Route index element={<MarketingHome />} />
90 <Route path="contact" element={<Contact />} />
91 </Route>
92
93 <Route path="projects">
94 <Route index element={<ProjectsHome />} />
95 <Route element={<ProjectsLayout />}>
96 <Route path=":pid" element={<Project />} />
97 <Route path=":pid/edit" element={<EditProject />} />
98 </Route>
99 </Route>
100</Routes>
101```
102
103## Index Routes
104
105Index routes render into their parent's `<Outlet/>` at their parent's URL (like a default child route). They are configured with the `index` prop:
106
107```tsx lines=[4,8]
108<Routes>
109 <Route path="/" element={<Root />}>
110 {/* renders into the outlet in <Root> at "/" */}
111 <Route index element={<Home />} />
112
113 <Route path="dashboard" element={<Dashboard />}>
114 {/* renders into the outlet in <Dashboard> at "/dashboard" */}
115 <Route index element={<DashboardHome />} />
116 <Route path="settings" element={<Settings />} />
117 </Route>
118 </Route>
119</Routes>
120```
121
122Note that index routes can't have children. If you're expecting that behavior, you probably want a [layout route](#layout-routes).
123
124## Route Prefixes
125
126A `<Route path>` _without_ an `element` prop adds a path prefix to its child routes, without introducing a parent layout.
127
128```tsx filename=app/routes.ts lines=[1]
129<Route path="projects">
130 <Route index element={<ProjectsHome />} />
131 <Route element={<ProjectsLayout />}>
132 <Route path=":pid" element={<Project />} />
133 <Route path=":pid/edit" element={<EditProject />} />
134 </Route>
135</Route>
136```
137
138## Dynamic Segments
139
140If 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 like `useParams`.
141
142```tsx
143<Route path="teams/:teamId" element={<Team />} />
144```
145
146```tsx filename=app/team.tsx
147import { useParams } from "react-router";
148
149export default function Team() {
150 let params = useParams();
151 // params.teamId
152}
153```
154
155You can have multiple dynamic segments in one route path:
156
157```tsx
158<Route
159 path="/c/:categoryId/p/:productId"
160 element={<Product />}
161/>
162```
163
164```tsx filename=app/category-product.tsx
165import { useParams } from "react-router";
166
167export default function CategoryProduct() {
168 let { categoryId, productId } = useParams();
169 // ...
170}
171```
172
173You should ensure that all dynamic segments in a given path are unique. Otherwise, as the `params` object is populated - latter dynamic segment values will override earlier values.
174
175## Optional Segments
176
177You can make a route segment optional by adding a `?` to the end of the segment.
178
179```tsx
180<Route path=":lang?/categories" element={<Categories />} />
181```
182
183You can have optional static segments, too:
184
185```tsx
186<Route path="users/:userId/edit?" element={<User />} />
187```
188
189## Splats
190
191Also known as "catchall" and "star" segments. If a route path pattern ends with `/*` then it will match any characters following the `/`, including other `/` characters.
192
193```tsx
194<Route path="files/*" element={<File />} />
195```
196
197```tsx
198let params = useParams();
199// params["*"] will contain the remaining URL after files/
200let filePath = params["*"];
201```
202
203You can destructure the `*`, you just have to assign it a new name. A common name is `splat`:
204
205```tsx
206let { "*": splat } = useParams();
207```
208
209## Linking
210
211Link to routes from your UI with `Link` and `NavLink`
212
213```tsx
214import { NavLink, Link } from "react-router";
215
216function Header() {
217 return (
218 <nav>
219 {/* NavLink makes it easy to show active states */}
220 <NavLink
221 to="/"
222 className={({ isActive }) =>
223 isActive ? "active" : ""
224 }
225 >
226 Home
227 </NavLink>
228
229 <Link to="/concerts/salt-lake-city">Concerts</Link>
230 </nav>
231 );
232}
233```
234
235---
236
237Next: [Navigating](./navigating)