Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 54

Implementing a 404 Catch-All Route

Recommended resources

Hello! Welcome to the final lesson in our module on React Router.

In our last session, we learned how to programmatically navigate using the useNavigate hook, a crucial skill for redirecting users after events like form submissions. You saw how this is conceptually similar to performing a redirect() in a Laravel controller.

Today, we'll address a final, essential piece of routing: handling invalid URLs. What happens when a user types a path into the address bar that doesn't exist in our application? Right now, they'd likely see a blank page. We'll fix this by implementing a "catch-all" route that displays a user-friendly "404 Not Found" page.

By the end of this lesson, you will be able to create a 'catch-all' route to display a 404 Not Found page for any unmatched URL.

1. The "Catch-All" Route Strategy

In web development, it's standard practice to provide a fallback for any request that doesn't match a defined route. In Laravel, you might use Route::fallback() for this. React Router achieves the same goal with a special route path: path="*".

The asterisk (*) acts as a wildcard that matches any URL. The key is that React Router evaluates routes in the order they are defined. Therefore, the catch-all route must always be the very last one in your <Routes> configuration. This ensures it only catches URLs that haven't been matched by any of the specific routes above it (like /, /about, or /products/:id).


2. Step 1: Create the NotFoundPage Component

First, let's create a dedicated component for our 404 page. This component will inform the user that the page doesn't exist and provide a link to return to the homepage.

  1. In your src/pages directory, create a new file named NotFoundPage.jsx.
  2. Add the following code to the file. This creates a simple page with a message and a Link back home.
// src/pages/NotFoundPage.jsx
import { Link } from 'react-router-dom';

const NotFoundPage = () => {
  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h1>404 - Page Not Found</h1>
      <p>Sorry, the page you are looking for does not exist.</p>
      <Link to="/" style={{ color: 'blue', textDecoration: 'underline' }}>
        Return to Homepage
      </Link>
    </div>
  );
};

export default NotFoundPage;

This is a simple but effective component. For a real-world application, you would style this page to match your brand's design.


3. Step 2: Configure the Catch-All Route

Now, let's wire this component into our routing setup. We'll add the path="*" route to our main router configuration file (likely App.jsx).

The following video provides a clear, quick demonstration of this exact process.

React Router 6 – Tutorial for Beginners

This short clip from a freeCodeCamp.org tutorial effectively demonstrates how to add a path="*" route to handle any unmatched URLs and render a custom error component.

Watch from 00:19:36 to 00:22:45 to see how to implement the catch-all route. Notice how the new <Route> is placed at the very end of the list.

As shown in the video, the implementation is straightforward.

  1. Open your App.jsx file.

  2. Import your new NotFoundPage component at the top:
    import NotFoundPage from './pages/NotFoundPage';

  3. Inside your <Routes> component, add the following <Route> as the very last entry:

    <Routes>
      {/* ... all your other routes ... */}
      <Route path="/products" element={<ProductsLayout />}>
        <Route index element={<ProductsPage />} />
        <Route path=":productId" element={<SingleProductPage />} />
      </Route>
      {/* ... more routes ... */}
    
      {/* This must be the last route */}
      <Route path="*" element={<NotFoundPage />} />
    </Routes>
    

Now, run your application and try navigating to a non-existent URL, like http://localhost:5173/some-random-page. You should see your custom NotFoundPage component.


4. Alternative: Redirecting Unmatched Routes

Sometimes, instead of showing a 404 page, you might prefer to simply redirect the user to the homepage. This can be a good user experience for simple URL typos. You can achieve this using the <Navigate> component.

Catch-All Routes for 404 Handling in React Router

This article from OpenReplay provides excellent code examples for handling 404s. We'll look at the redirect alternative and a summary of when to use each approach.

Please read the following two short sections: "Alternative: Redirect Approach Using Navigate": This shows the code for using the <Navigate> component in a catch-all route. "When to Use Redirects vs Custom Pages": This provides a clear comparison to help you decide which strategy is best for your project.

To implement this, you would replace your NotFoundPage route with this:

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

// ... inside your Routes component
<Route path="*" element={<Navigate to="/" replace />} />

The replace prop is important here. As we discussed in the previous lesson, it replaces the bad URL in the browser's history, so the user won't get stuck in a loop if they use the "Back" button.

So, which should you choose?

  • Custom 404 Page (<NotFoundPage />): The best practice for most applications. It gives clear feedback to the user and is better for Search Engine Optimization (SEO), as it allows servers to return a proper 404 status code.
  • Redirect (<Navigate />): A simpler approach that can be useful for small sites where invalid URLs are likely just typos. It prioritizes a seamless experience over explicit error feedback.

For our e-commerce project, and for most projects you'll build, a custom 404 page is the recommended approach.


Conclusion

Congratulations on completing the module on client-side routing! You now have a solid foundation for building the navigation structure of any single-page application.

Key Takeaways:

  • A catch-all route with path="*" is used to handle URLs that don't match any other defined routes.
  • This route must be placed last inside the <Routes> component to function correctly.
  • You can either render a custom NotFoundPage component to inform the user of the error or use the <Navigate> component to redirect them to a valid page like the homepage.
  • Using a custom 404 page is generally the preferred and more professional approach.

Preview of the Next Module:

We've done a lot with components, props, and routing. Now, we're going to dive deeper into what makes React truly powerful: managing state. In our next module, "Advanced Hooks and Global State," we'll move beyond the basic useState hook. Our first lesson will introduce the useReducer hook, a robust tool for managing complex state logic in a more predictable and scalable way—perfect for things like a shopping cart or multi-step forms.