Part 28: Programmatic Navigation, Redirects & 404 Pages
Not all navigation happens when a user clicks a link. Often you must navigate after an asynchronous operation completes (like logging in, submitting a payment, or encountering an unauthorized error).
1. Programmatic Navigation with useNavigate
The useNavigate hook returns an imperative navigation function:
import { useNavigate } from 'react-router-dom';
export default function CheckoutForm() {
const navigate = useNavigate();
const handlePayment = async () => {
// 1. Process payment via API...
const success = true;
if (success) {
// 2. Navigate to order confirmation and pass state
navigate('/order-success', {
replace: true, // Replaces current entry in history stack
state: { orderId: 'ORD-9821' }
});
}
};
return (
<div>
<button onClick={handlePayment} className="btn-primary">
Complete Purchase
</button>
<button onClick={() => navigate(-1)} className="btn-secondary ml-2">
Go Back
</button>
</div>
);
}
2. Reading Navigation State
In the destination component:
import { useLocation } from 'react-router-dom';
export default function OrderSuccess() {
const location = useLocation();
const orderId = location.state?.orderId;
return (
<div className="p-6 text-center">
<h2>Thank you for your order!</h2>
{orderId && <p>Order Reference: <strong>{orderId}</strong></p>}
</div>
);
}
3. Catch-All 404 Not Found Routes
Use path="*" to catch any route that doesn't match predefined paths:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{/* Catch-all 404 */}
<Route path="*" element={<NotFoundPage />} />
</Routes>
Key Takeaways
- Use
useNavigate()for imperative navigation following async events. - Pass
replace: trueto prevent users from navigating back to completed submission steps. - Use
path="*"to render a custom 404 screen for unmatched routes.
In Part 29, we will implement Protected Routes and Authentication Guards!

