M4: Routes & Navigation
L11: Programmatic Navigation
Navigate using JavaScript with the useNavigate hook
Sometimes you need to navigate from JavaScript code - after form submissions, button clicks, or timed actions. The useNavigate hook lets you control navigation programmatically!
What You'll Learn
- Use the useNavigate hook
- Navigate after actions/events
- Pass
statebetween routes - Navigate with replace option
- Go forward/backward in history
useNavigate Hook
import { useNavigate } from 'react-router-dom';
function Component() {
const navigate = useNavigate();
const handleClick = () => {
navigate('/destination');
};
return <button onClick={handleClick}>Go</button>;
}Common Use Cases
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
function BookingForm() {
const navigate = useNavigate();
const [formData, setFormData] = useState({});
const handleSubmit = async (e) => {
e.preventDefault();
// Submit booking
const booking = await createBooking(formData);
// Navigate to confirmation page
navigate(`/booking/${booking.id}/confirm`);
};
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
<button type="submit">Book Now</button>
</form>
);
}function DeleteButton({ listingId }) {
const navigate = useNavigate();
const [isDeleting, setIsDeleting] = useState(false);
const handleDelete = async () => {
setIsDeleting(true);
try {
await fetch(`/api/listings/${listingId}`, {
method: 'DELETE'
});
// Navigate back to listings after delete
navigate('/');
} catch (error) {
alert('Failed to delete');
setIsDeleting(false);
}
};
return (
<button
onClick={handleDelete}
disabled={isDeleting}
>
{isDeleting ? 'Deleting...' : 'Delete Listing'}
</button>
);
}function ProtectedPage() {
const navigate = useNavigate();
const isAuthenticated = useAuth();
useEffect(() => {
if (!isAuthenticated) {
// Redirect to login if not authenticated
navigate('/login');
}
}, [isAuthenticated, navigate]);
return <div>Protected content</div>;
}function SuccessPage() {
const navigate = useNavigate();
useEffect(() => {
// Redirect after 3 seconds
const timer = setTimeout(() => {
navigate('/');
}, 3000);
return () => clearTimeout(timer);
}, [navigate]);
return (
<div>
<h1>Success! ✅</h1>
<p>Redirecting to home in 3 seconds...</p>
</div>
);
}Navigate Options
// Access in destination component
import { useLocation } from 'react-router-dom';
function SuccessPage() {
const location = useLocation();
const bookingId = location.state?.bookingId;
const from = location.state?.from;
return <div>Booking #{bookingId} from {from}</div>;
}Practical Example: Add to Booking
Let's add a "Book Now" feature that navigates to a booking page:
Update ListingDetailsCard
Add booking button logic:
import { useNavigate } from 'react-router-dom';
export default function ListingDetailsCard({ listing }) {
const navigate = useNavigate();
const handleBooking = () => {
// Navigate to booking page with listing data
navigate(`/booking/${listing.id}`, {
state: { listing: { id: listing.id, title: listing.title, price: listing.price } }
});
};
return (
<div className="container mx-auto px-4 py-8">
{/* ... existing content ... */}
{/* Booking Card */}
<div className="lg:col-span-1">
<div className="border border-gray-200 rounded-lg p-6 shadow-md sticky top-4">
<div className="mb-4">
<span className="text-2xl font-bold">${listing.price}</span>
<span className="text-gray-600"> / night</span>
</div>
<button
onClick={handleBooking} {}
className="w-full bg-pink-600 hover:bg-pink-700 text-white font-semibold py-3 px-6 rounded-lg transition-colors"
>
Check Availability
</button>
</div>
</div>
</div>
);
}Create Booking Page (Optional)
import { useParams, useLocation, useNavigate } from 'react-router-dom';
export default function BookingPage() {
const { id } = useParams();
const location = useLocation();
const navigate = useNavigate();
const listing = location.state?.listing;
if (!listing) {
return <div>No listing data</div>;
}
const handleConfirmBooking = () => {
// Process booking...
navigate('/booking-confirmed', {
state: { bookingId: 123 }
});
};
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold mb-4">
Book {listing.title}
</h1>
<p className="text-xl mb-6">
${listing.price} / night
</p>
<button
onClick={handleConfirmBooking}
className="bg-pink-600 text-white px-6 py-3 rounded-lg"
>
Confirm Booking
</button>
<button
onClick={() => navigate(-1)}
className="ml-4 bg-gray-200 px-6 py-3 rounded-lg"
>
Cancel
</button>
</div>
);
}useNavigate vs Link
Use <Link> for:
- User-initiated clicks
- Standard navigation
- Crawlable links (SEO)
- Keyboard accessibility
- Right-click → Open in new tab
Examples:
// ✅ Navigation menu
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
// ✅ Card links
<Link to={`/listing/${id}`}>
<div className="card">...</div>
</Link>
// ✅ Buttons that look like links
<Link to="/signup" className="btn">
Sign Up
</Link>Common Patterns
Programmatic Navigation Mastered!
You now know how to navigate from JavaScript code! This is essential for forms, authentication, and complex user flows.
Quick Recap
What we learned:
- ✅ useNavigate hook for programmatic navigation
- ✅ Navigate after form submissions
- ✅ Pass
statebetween routes - ✅ Replace history entries
- ✅ Navigate backward/forward
Key concepts:
- useNavigate() - Returns navigation function
- navigate(path) - Navigate to path
- navigate(path,
{ state }) - Pass data - navigate(path,
{ replace }) - Replace history - navigate(-1) - Go back
What's Next?
In Lesson 12, we'll review all Module 4 concepts - routes, parameters, navigation, and best practices. Time to consolidate everything you've learned! 📚