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.
- In your
src/pagesdirectory, create a new file namedNotFoundPage.jsx. - Add the following code to the file. This creates a simple page with a message and a
Linkback 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.
-
Open your
App.jsxfile. -
Import your new
NotFoundPagecomponent at the top:import NotFoundPage from './pages/NotFoundPage'; -
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
NotFoundPagecomponent 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.