Handling 404 Pages
In this page:
Adding a Catch-All Route
A Route defined with path='*' matches literally any URL that no earlier route already matched. Placing this as the last Route inside your Routes block gives unmatched URLs somewhere to land instead of showing a blank page.
Note: Test your 404 page by visiting a made-up URL like /this-does-not-exist during development.
Warning: A wildcard route placed before your real routes will match everything first, preventing any of your actual pages from ever rendering.
Example: Adding a Catch-All Route
// Run in your local React project (npm install required)
import { Routes, Route } from 'react-router-dom';
function Home() { return <p>Home</p>; }
function NotFound() { return <h1>404 - Page Not Found</h1>; }
function AppRoutes() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="*" element={<NotFound />} />
</Routes>
);
}
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Making the 404 Page Helpful
A good 404 page does more than say 'not found' — it reassures the user and gives them an obvious way to recover, usually a link back to the homepage or a search box. This turns a dead end into a small, graceful redirect.
Note: Include a Link (not a plain <a>) back to home, so recovering from a 404 stays a smooth client-side navigation.
Warning: A bare 404 with no explanation or way out is a poor experience — always give the user their next step.
Example: Making the 404 Page Helpful
// Run in your local React project (npm install required)
import { Link } from 'react-router-dom';
function NotFound() {
return (
<div>
<h1>404 - Page Not Found</h1>
<p>Sorry, that page doesn't exist.</p>
<Link to="/">Go back home</Link>
</div>
);
}
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Nested 404s for a Specific Section
The same wildcard pattern works inside nested routes too, letting a specific section of your app (like /dashboard/*) show its own contextual 'not found' message rather than the app-wide one, while other sections still use the global 404.
Note: A section-specific 404 can keep the section's shared layout (like a sidebar) visible, which the global 404 usually wouldn't.
Warning: Having both a global and several nested wildcard routes can get confusing — document clearly which one handles which cases.
Example: Nested 404s for a Specific Section
// Run in your local React project (npm install required)
import { Routes, Route, Outlet } from 'react-router-dom';
function DashboardLayout() { return <div><nav>Dashboard Nav</nav><Outlet /></div>; }
function DashboardNotFound() { return <p>No such dashboard page</p>; }
function AppRoutes() {
return (
<Routes>
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="*" element={<DashboardNotFound />} />
</Route>
</Routes>
);
}
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
- Forgetting to add a wildcard route at all, leaving unmatched URLs rendering completely blank.
- Placing the wildcard route somewhere other than last, letting it accidentally swallow other routes.
- Not giving the 404 page a way back to safety, like a link to the home page.
- A Route with path='*' matches any URL not matched by an earlier, more specific route.
- It must be the last Route inside Routes so it doesn't shadow real pages.
- A good 404 page explains what happened and offers a link back to a known-good page.
- This pattern also works for nested routes, catching unmatched paths within a specific section.
Requires npm install react-router-dom — not available via CDN in this sandbox.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: