Search code examples
reactjsreact-routerreact-router-dom

Redirect All Matches of Path without Root Folder in React Router


I'm using react-router-dom version 6.3.0 and I'm trying to make my router handle an updated URL structure.

As an example, my old routes look like this:

<Route path='animals/dog' element={<Dog />} />
<Route path='animals/cat' element={<Cat />} />
<Route path='animals/bird/songs' element={<BirdSongs />} />

And I want them to automatically redirect without the root folder animals:

<Route path='dog' element={<Dog />} />
<Route path='cat' element={<Cat />} />
<Route path='bird/songs' element={<BirdSongs />} />

Everything needs to redirect to where it previously went, but I don't want to have to manually write a redirect for every possible Route in my app.

Is that doable with React Router? In my situation, I'm not able to use .htaccess or 301 redirects. It has to happen in React Router itself.


Solution

  • You can create a custom component to match any "/animals/*" route and redirect to the appropriate "root" route.

    Example:

    import { Navigate, useParams } from "react-router-dom";
    
    const RedirectAnimals = ({ base = "/" }) => {
      // Grab the rest of the path after "/animals", i.e. "dog", "cat", etc
      const { "*": path } = useParams();
    
      // Create redirect target path
      // e.g. from "/animals/foo/bar" to "/foo/bar"
      const target = `${base}${path}`;
    
      // Redirect to new target path
      return <Navigate to={target} replace />;
    };
    

    Render RedirectAnimals route.

    <Routes>
      ...
      <Route path="animals/*" element={<RedirectAnimals />} />
      ...
      <Route path="dog" element={<Dog />} />
      <Route path="cat" element={<Cat />} />
      <Route path="bird/songs" element={<BirdSongs />} />
      ...
    </Routes>