← Back to React Course | Chapter 8: Routing | Lesson 7 of 10

Programmatic Navigation

Programmatic navigation is like telling your GPS to go somewhere by voice command, instead of physically clicking a link on the map.

Navigating After an Action, Not a Click

Sometimes navigation needs to happen as a result of code running, like redirecting after a successful form submission, rather than the user clicking a Link directly. The useNavigate() hook returns a function you can call from inside any event handler or effect to trigger that navigation.

Note: Call navigate() right after your async submit logic succeeds, so the redirect only happens if the action actually worked.

Warning: useNavigate() must be called inside a component rendered within a BrowserRouter — calling it outside that context throws an error.

Example: Navigating After an Action, Not a Click

markup
// Run in your local React project (npm install required)
import { useNavigate } from 'react-router-dom';

function LoginForm() {
  const navigate = useNavigate();
  const handleSubmit = e => {
    e.preventDefault();
    navigate('/dashboard');
  };
  return <form onSubmit={handleSubmit}><button type="submit">Log In</button></form>;
}

⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.

Going Back with navigate(-1)

Passing a negative number to navigate acts like the browser's back button, moving that many steps backward through history. navigate(-1) goes back one page, mimicking a Cancel or Back button's natural behavior.

Note: This is a nice way to implement a generic Back button that works no matter where the user came from.

Warning: If there's no previous entry in history (e.g. the user landed directly on this page), navigate(-1) can navigate away from your app entirely.

Example: Going Back with navigate(-1)

markup
// Run in your local React project (npm install required)
import { useNavigate } from 'react-router-dom';

function BackButton() {
  const navigate = useNavigate();
  return <button onClick={() => navigate(-1)}>Go Back</button>;
}

⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.

Replacing History Instead of Pushing

By default, navigate('/path') adds a new entry to browser history, so the back button returns to the previous page. Passing { replace: true } as a second argument instead swaps out the current entry, which is useful after a login redirect so the back button doesn't return to the login form.

Note: Use replace:true for redirects the user shouldn't be able to undo with the back button, like post-login or post-logout redirects.

Warning: Overusing replace:true elsewhere can confuse users by breaking their expected back-button behavior.

Example: Replacing History Instead of Pushing

markup
// Run in your local React project (npm install required)
import { useNavigate } from 'react-router-dom';

function LoginForm() {
  const navigate = useNavigate();
  const handleSubmit = e => {
    e.preventDefault();
    navigate('/dashboard', { replace: true });
  };
  return <form onSubmit={handleSubmit}><button type="submit">Log In</button></form>;
}

⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.

Common Mistakes
  1. Trying to use the old useHistory hook, which was removed in React Router v6 in favor of useNavigate.
  2. Calling useNavigate() outside of a component that's rendered inside a BrowserRouter.
  3. Forgetting that navigate('/path') by default adds to browser history — use { replace: true } if you want to replace instead.
Chapter Summary
  • useNavigate() returns a function you call to change routes from inside event handlers or effects.
  • navigate('/path') pushes a new entry onto browser history, same as clicking a Link.
  • navigate(-1) goes back one step in history, like the browser's back button.
  • { replace: true } as a second argument replaces the current history entry instead of adding a new one.
Browser Support

Requires npm install react-router-dom (v6 useNavigate) — not available via CDN in this sandbox; v5 used useHistory instead.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.