Restricting dynamic segments to certain values in React Router v6?

Viewed 18

The URL structure we're implementing has URLS like mysite.com/en/some-page where en is the language the page is translated into. A simplified example of my code would be:

<Router>
    <Routes>
        <Route path="/" element={<RedirectToLocale />} />
        <Route path="/:locale">
            <Route index element={<Home />} />
            <Route path="about" element={<About />} />
            <Route path="news" element={<News />} />
            <Route path="*" element={<NotFound />} />
        </Route>
        <Route path="*" element={<NotFound />} />
    </Routes>
</Router>

RedirectToLocale simply redirects someone to the appropriate locale if they hit the base page.

The issue is this shows the home page for mysite.com/en (good) and mysite.com/asdf (bad). The latter should be caught by * as an error.

Previous versions of React Router had some level of RegEx support for Dynamic Segments but it seems v6 does not. Is there a way I can limit :locale to only known good strings and let the normal * match catch anything else?

I'm hoping the answer isn't "hard-code all your locales"...

1 Answers

Generally the answer is to hardcode the locales via layout routes, but if you want to render only a single layout route you can read and test the locale route path parameter in the layout component and redirect off the route if the parameter value is invalid.

Example testing for English|French locales:

console.log(/en|fr/gi.test("de"));
console.log(/en|fr/gi.test("en"));
console.log(/en|fr/gi.test("fr"));

import { Navigate, Outlet } from 'react-router-dom';

const LocaleLayout = () => {
  const { locale } = useParams();
  const isValidLocale = /en|fr/gi.test(locale);
  return isValidLocale
    ? <Outlet />
    : <Navigate to="/" replace />;
};

...

<Router>
  <Routes>
    <Route path="/" element={<RedirectToLocale />} />
    <Route path="/:locale" element={<LocaleLayout />}>
      <Route index element={<Home />} />
      <Route path="about" element={<About />} />
      <Route path="news" element={<News />} />
      <Route path="*" element={<NotFound />} />
    </Route>
    <Route path="*" element={<NotFound />} />
  </Routes>
</Router>
Related