Home > Enterprise >  How to restrict url params to a certain set of values using react router?
How to restrict url params to a certain set of values using react router?

Time:11-29

I am using react router v6 to define routes like this.

<Routes>  
  <Route path="*" element={<Navigate to="/" />} />
  <Route path="/" element={<HomePage />} />
  <Route path="/shop">
    <Route index element={<ShopPage />} />
    <Route path=":category" element={<CategoryPage />} />
  </Route>
</Routes>

Here's the ShopPage code to navigate to "/shop/:category"

const categories = ['shoes', 'jeans', 'sweaters']; // originally populated using an api 
{categories.map(category => <Link to=`/shop/${category}`>${category}</Link>}

I want to restrict navigating to CategoryPage only when the category param has a value from the above defined set. What I'm doing currently is conditionally rendering stuff on CategoryPage depending on category param received.

For example, if user navigates to "/shop/xyz", I just show a 'not found' error & a link to go back to shop. What I would like though is to somehow pre-check destination path and to not move to CategoryPage at all in this case.

I tried to do something like

 <Route path=":category('shoes'|'jeans'|'sweaters')" element={<CategoryPage />} />

as mentioned in this post but that just redirects me to root path '/' for all param values.

Is there a way to do this?

CodePudding user response:

Regular expressions were removed from route paths in react-router-dom@6. See "What Happened to Regexp Routes Paths?" for details.

You've a couple options:

  1. Explicitly render the routes you want to match. For this you map the categories in the same way as you did the links.

    <Routes>  
      <Route path="*" element={<Navigate to="/" />} />
      <Route path="/" element={<HomePage />} />
      <Route path="/shop">
        <Route index element={<ShopPage />} />
        {categories.map(category => (
          <Route
            key={category}
            path={category} // <-- "/shop/shoes", "/shop/jeans", "/shop/sweaters"
            element={<CategoryPage />}
          />
        ))}
      </Route>
    </Routes>
    
  2. Validate the category route path parameter in a matched component. I'd suggest creating a category wrapper component that reads and validates the category path parameter and bounces a user off the route if the category isn't valid.

    import { Navigate, useParams } from 'react-router-dom';
    
    const CategoryWrapper = ({ categories = [], children }) => {
      const { category } = useParams();
    
      const isValid = !categories.length || categories.includes(category);
    
      return isValid ? children : <Navigate to="/" replace />;
    };
    
    <Routes>  
      <Route path="*" element={<Navigate to="/" />} />
      <Route path="/" element={<HomePage />} />
      <Route path="/shop">
        <Route index element={<ShopPage />} />
        <Route
          path=":category"
          element={(
            <CategoryWrapper categories={categories}>
              <CategoryPage />
            <CategoryWrapper>
          )}
        />
      </Route>
    </Routes>
    
  • Related