Using useNavigate() outside 

Loading

Proper Usage of useNavigate() in React Router

A common error in React Router v6+ occurs when trying to use the useNavigate() hook outside of a <Router> context. This hook requires access to the routing context provided by React Router’s router components.

The Error Scenario

// ❌ Wrong - using useNavigate outside Router context
function StandaloneButton() {
  const navigate = useNavigate(); // Error!
  return <button onClick={() => navigate('/')}>Home</button>;
}

function App() {
  return (
    <div>
      <StandaloneButton />
    </div>
  );
}

Correct Solutions

1. Wrap Your App with a Router

// ✅ Correct - entire app inside Router
import { BrowserRouter as Router } from 'react-router-dom';

function App() {
  return (
    <Router>
      {/* All routing-dependent components */}
      <StandaloneButton />
    </Router>
  );
}

function StandaloneButton() {
  const navigate = useNavigate(); // Works now
  return <button onClick={() => navigate('/')}>Home</button>;
}

2. Alternative: Pass navigate as a Prop

// ✅ Alternative pattern
function App() {
  return (
    <Router>
      <Layout>
        <Routes>
          <Route path="/" element={<Home />} />
        </Routes>
      </Layout>
    </Router>
  );
}

function Layout({ children }) {
  const navigate = useNavigate();
  return (
    <div>
      <NavBar navigate={navigate} />
      {children}
    </div>
  );
}

function NavBar({ navigate }) {
  // Receives navigate as prop from parent
  return <button onClick={() => navigate('/')}>Home</button>;
}

Common Use Cases

1. Programmatic Navigation

function LoginForm() {
  const navigate = useNavigate();

  const handleSubmit = async () => {
    await loginUser();
    navigate('/dashboard'); // Redirect after login
  };

  return <form onSubmit={handleSubmit}>...</form>;
}

2. Navigation in Custom Hooks

function useAuth() {
  const navigate = useNavigate();

  const login = async () => {
    await authenticate();
    navigate('/profile');
  };

  return { login };
}

Troubleshooting

If you’re still seeing errors:

  1. Verify you’re using React Router v6+ (earlier versions used useHistory)
  2. Check your router import matches your routing style:
   import { BrowserRouter, HashRouter, MemoryRouter } from 'react-router-dom';
  1. Ensure no component using useNavigate renders before the <Router>
  2. For testing, you may need to wrap components in a MemoryRouter

Testing Components with useNavigate

// In your test file
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';

test('navigates on click', () => {
  render(
    <MemoryRouter>
      <ComponentUsingNavigate />
    </MemoryRouter>
  );
  // Test implementation
});

Remember that useNavigate() is a hook that requires the React Router context to be available in the component hierarchy. Always ensure your navigation-dependent components are rendered within a router component.

Leave a Reply

Your email address will not be published. Required fields are marked *