Code To Learn logo

Code To Learn

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 state between 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>
  );
}

SuccessPage.jsx
// 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:

src/components/ListingDetailsCard.jsx
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)

src/pages/BookingPage.jsx
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>
  );
}

Use useNavigate() for:

  • After form submissions
  • After async operations
  • Conditional redirects
  • Programmatic flow control
  • After timers/delays

Examples:

// ✅ After form submit
const handleSubmit = async () => {
  await submitForm();
  navigate('/success');
};

// ✅ Conditional redirect
if (!isAuthenticated) {
  navigate('/login');
}

// ✅ After API call
const handleDelete = async () => {
  await deleteItem();
  navigate('/');
};

// ✅ With state data
navigate('/checkout', {
  state: { cart: items }
});

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 state between 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! 📚