reactjsreact-routerdynamic-routing

404 page not found not working react-router v6 (using more than one param)


My shallow understanding is causing a simple issue with rendering the NotFound page...

<Routes>
          <Route path="*" element={<NotFound />}/>
          <Route path="/" element={<Home />} />
          <Route path="/:category/:id" element={<Article />} />
        </Routes>

When the uri contains one "/", it renders the matching component or NotFound component, however, when the uri includes two "/", for example "/asoejdnxx/acnoiw" which doesn't exist, it doesn't route to the NotFound page but just renders a blank page with no errors.

I'm assuming the issue is because react is looking for the params in the thirds Route(which has the :category and :id param) regardless of it matching or not.

I'm sure there should be no need to add a condition in the "Article" component, such as if the param doesn't match to an existing :id, render something else(since thats the purpose of path="*"), but i cant find a way to redirect or render the NotFound component.


Solution

  • What makes you think that "/asoejdnxx/acnoiw" wouldn't be matched by path="/:category/:id" and render the "404" route and NotFound component instead?

    For URL path "/asoejdnxx/acnoiw" the path="/:category/:id" will match it and render the Article component. It's at this point that Article needs to validate the route params it's consuming and if they are invalid, redirect to the 404 route.

    I suggest actually creating a 404 route that you can redirect to.

    Example:

    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/:category/:id" element={<Article />} />
      <Route path="notfound" element={<NotFound />} />
      <Route path="*" element={<Navigate to="/notfound" replace />} />
    </Routes>
    

    In the Article component use a useEffect hook to redirect to "/notfound" under the correct circumstances.

    Example:

    const { category, id } = useParams();
    const navigate = useNavigate();
    
    ...
    
    useEffect(() => {
      if (/* invalid route params */) {
        navigate("/notfound", { replace: true });
      }
    }, [category, id, navigate]);