Search code examples
javascriptreactjsreact-router-dom

How to redirect a page under a condition?


I wrote the Routes in my project as below:

<Routes>
  <Route exact path="/" element={<Home />} />
  <Route exact path='/login' element={<Login />} /> 
  <Route exact path='/about' element={<About />} />
  <Route exact path='/store' element={<Store />} />
  <Route exact path='/store/:productID' element={<Product />} />
  <Route path={['/not-found', '*']} element={<NotFound />} /> 
</Routes>

In Product page I want to display the existing product ids and redirect the other ones to not-found page:

{!check && navigate("/not-found", {replace: true})}
<div className="container">
  <ul>
    <li>Product ID: {productID}</li>
    <li>Name: {check.name}</li>
    <li>Price: {check.price}</li>
    <li><img src={check.image} /></li>
  </ul>
</div>

but I'm getting this error: Uncaught TypeError: meta.relativePath.startsWith is not a function

I also wrote it with navigate component:

{!check && <Navigate to="/not-found" />}

Still displays a white page for not existing ids.


Solution

  • The Route component's path prop takes only a string value, not an array. You'll need to split the two route paths up. I suggest rendering the NotFound component on path="/not-found" and redirect all unhandled/unknown paths to it.

    Example:

    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/login" element={<Login />} /> 
      <Route path="/about" element={<About />} />
      <Route path="/store" element={<Store />} />
      <Route path="/store/:productID" element={<Product />} />
      <Route path="/not-found" element={<NotFound />} />
      <Route path="*" element={<Navigate to="/not-found" replace />} />
    </Routes>
    

    The product page should also render the Navigate component if you are trying to apply the redirect logic in the render return.

    {check
      ? (
        <div className="container">
          <ul>
            <li>Product ID: {productID}</li>
            <li>Name: {check.name}</li>
            <li>Price: {check.price}</li>
            <li><img src={check.image} /></li>
          </ul>
        </div>
      )
      : <Navigate to="/not-found" replace />
    }
    

    Otherwise the navigate function should only be called in a callback or useEffect hook.

    useEffect(() => {
      if (!check) {
        navigate("/not-found", { replace: true });
      }
    }, [check]);
    
    ...
    
    if (!check) {
      return null;
    }
    
    return (
      ...
      <div className="container">
        <ul>
          <li>Product ID: {productID}</li>
          <li>Name: {check.name}</li>
          <li>Price: {check.price}</li>
          <li><img src={check.image} /></li>
        </ul>
      </div>
      ...
    );