You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/getting-started/faq.md
+166Lines changed: 166 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -193,3 +193,169 @@ function MatchPath({ path, Comp }) {
193
193
// Will match anywhere w/o needing to be in a `<Routes>`
194
194
<MatchPathpath="/accounts/:id"Comp={Account} />;
195
195
```
196
+
197
+
## What Happened to Regexp Routes Paths?
198
+
199
+
Regexp route paths were removed for two reasons:
200
+
201
+
1. Regular expression paths in routes raised a lot of questions for v6's ranked route matching. How do you rank a regex?
202
+
203
+
2. We were able to shed an entire dependency (path-to-regexp) and cut the package weight sent to your user's browser significantly. If it were added back, it would represent 1/3 of React Router's page weight!
204
+
205
+
After looking at a lot of use cases, we found we can still meet them without direct regexp path support, so we made the tradeoff to significantly decrease the bundle size and avoid the open questions around ranking regexp routes.
206
+
207
+
The majority of regexp routes were only concerned about one URL segment at a time and doing one of two things:
208
+
209
+
1. Matching multiple static values
210
+
2. Validating the param in some way (is a number, not a number, etc.)
211
+
212
+
**Matching generally static values**
213
+
214
+
A very common route we've seen is a regex matching multiple language codes:
215
+
216
+
```tsx filename=v5-regex-route.js
217
+
functionApp() {
218
+
return (
219
+
<Switch>
220
+
<Route path={/(en|es|fr)/} component={Lang} />
221
+
</Switch>
222
+
);
223
+
}
224
+
225
+
functionLang({ params }) {
226
+
let lang = params[0];
227
+
let translations = I81n[lang];
228
+
// ...
229
+
}
230
+
```
231
+
232
+
These are all actually just static paths, so in v6 you can make three routes and pass the code directly to the component. If you've got a lot of them, make an array and map it into routes to avoid the repetition.
233
+
234
+
```tsx filename=v6.js
235
+
functionApp() {
236
+
return (
237
+
<Routes>
238
+
<Route path="en" element={<Lang code="en"/>} />
239
+
<Route path="es" element={<Lang code="en"/>} />
240
+
<Route path="fr" element={<Lang code="en"/>} />
241
+
</Routes>
242
+
);
243
+
}
244
+
245
+
functionLang({ lang }) {
246
+
let translations = I81n[lang];
247
+
// ...
248
+
}
249
+
```
250
+
251
+
**Doing some sort of param validation**
252
+
253
+
Another common case was ensuring that parameters were an integer.
254
+
255
+
```tsx filename=v5-regex-route.js
256
+
functionApp() {
257
+
return (
258
+
<Switch>
259
+
<Route path={/users\/(\d+)/} component={User} />
260
+
</Switch>
261
+
);
262
+
}
263
+
264
+
functionUser({ params }) {
265
+
let id = params[0];
266
+
// ...
267
+
}
268
+
```
269
+
270
+
In this case you have to do a bit of work yourself with the regex inside the matching component:
Looking at this example you might be concerned that in the v6 version your other routes won't get rendered at their URLs because the `:userId` route might match first. But, thanks to route ranking, that is not the case. The "new" and "inactive" routes will rank higher and therefore render at their respective URLs:
In fact, the v5 version has all sorts of problems if your routes aren't ordered _just right_. V6 competely eliminates this problem.
334
+
335
+
**Remix Users**
336
+
337
+
If you're using [Remix](https://remix.run), you can send proper 40x responses to the browser by moving this work into your loader. This also decreases the size of the browser bundles sent to the user because loaders only run on the server.
338
+
339
+
```tsx
340
+
import { useLoaderData } from"remix";
341
+
342
+
exportasyncfunction loader({ params }) {
343
+
if (!params.id.match(/\d+/)) {
344
+
thrownewResponse("", { status: 400 });
345
+
}
346
+
347
+
let user =awaitfakeDb.user.find({ where: { id: params.id=}})
348
+
if (!user) {
349
+
thrownewResponse("", { status: 404})
350
+
}
351
+
352
+
returnuser;
353
+
}
354
+
355
+
function User() {
356
+
let user =useLoaderData();
357
+
// ...
358
+
}
359
+
```
360
+
361
+
Instead of rending your component, remix will render the nearest [catch boundary](https://docs.remix.run/v0.20/api/app/#catchboundary) instead.
0 commit comments