How to Implement React Router DOM History Push in Functional Components Using Hooks

Use the useHistory hook in React Router DOM v5 or the useNavigate hook in v6 to programmatically push new entries onto the history stack from within functional components.

React Router DOM provides specialized hooks that enable imperative navigation without relying on class-based higher-order components. Whether you are maintaining a legacy codebase or building a new application with the facebook/react ecosystem, understanding how to implement react router dom history push using modern hooks is essential for managing client-side routing.

React Router DOM History Push: Version Differences

React Router DOM offers two primary hook APIs for navigation depending on your version:

  • React Router DOM v5: Uses the useHistory hook, which returns a history object mirroring the classic history API with methods like push, replace, and goBack.
  • React Router DOM v6: Uses the useNavigate hook, which returns a navigate function that internally calls history.push or history.replace while supporting relative navigation.

Both hooks are designed exclusively for functional components and guarantee that the navigation object is tied to the nearest <Router> context in the component tree.

Implementing History Push with useHistory in React Router DOM v5

When working with React Router DOM v5, you import useHistory from react-router-dom and invoke it at the top level of your functional component.

Code Example: Functional Component with useHistory

import React from 'react';
import { useHistory } from 'react-router-dom';

export default function MyComponent() {
  // Obtain the history object from the Router context
  const history = useHistory();

  // Handler that pushes a new entry onto the history stack
  const goToAbout = () => {
    history.push('/about');
  };

  return (
    <button onClick={goToAbout}>Go to About page</button>
  );
}

In the facebook/react repository, the fixture at fixtures/nesting/src/modern/App.js demonstrates a functional component wrapped with <BrowserRouter>. You can adapt this pattern by importing useHistory inside any child component to access the history instance and call history.push programmatically.

Implementing History Push with useNavigate in React Router DOM v6

React Router DOM v6 replaces useHistory with useNavigate, offering a more streamlined API for functional components.

import React from 'react';
import { useNavigate } from 'react-router-dom';

export default function MyComponent() {
  // Get the navigate function
  const navigate = useNavigate();

  // Push a new entry onto the history stack
  const goToAbout = () => {
    navigate('/about');
  };

  // Replace the current entry instead of pushing
  const replaceLogin = () => {
    navigate('/login', { replace: true });
  };

  return (
    <div>
      <button onClick={goToAbout}>Go to About page</button>
      <button onClick={replaceLogin}>Replace with Login</button>
    </div>
  );
}

Relative Navigation in React Router DOM v6

The useNavigate hook supports relative navigation, which is useful when building nested route structures:

navigate('details', { relative: 'path' }); // Pushes /current/path/details

This approach eliminates the need to manually construct URLs when navigating from deeply nested components.

Common Pitfalls When Using React Router DOM History Push Hooks

  • Using hooks outside a Router context. Ensure the component tree includes <BrowserRouter>, <HashRouter>, or <MemoryRouter> from react-router-dom before calling useHistory or useNavigate.

  • Missing dependency in package.json. Run npm install react-router-dom@^6 (or @5 for legacy projects) to ensure the hook APIs are available in your application.

  • Navigation during render phase. Call push or navigate inside event handlers, useEffect, or callbacks. Never invoke these functions directly in the component body during render, as navigation is a side effect.

  • Mixing v5 and v6 APIs. Stick to one version per project. v6 is the default for new projects and offers better TypeScript support, while v5 requires the useHistory pattern.

  • Missing fallback UI for async routes. Wrap routes in <Suspense> and render a loader while code-splitting loads the target component.

Full Integration Example: React Router DOM History Push in Action

The following example demonstrates a complete application using React Router DOM v6 with the useNavigate hook for programmatic navigation:

import React, { Suspense } from 'react';
import { BrowserRouter, Routes, Route, useNavigate } from 'react-router-dom';
import Home from './Home';
import About from './About';

function NavButton() {
  const navigate = useNavigate();
  return (
    <button onClick={() => navigate('/about')}>
      Go to About
    </button>
  );
}

export default function App() {
  return (
    <BrowserRouter>
      <div>
        <NavButton />
        <Suspense fallback={<div>Loading…</div>}>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
          </Routes>
        </Suspense>
      </div>
    </BrowserRouter>
  );
}

This implementation follows the patterns found in the facebook/react repository's nesting fixtures, where functional components are wrapped with <BrowserRouter> and navigation is handled via hooks rather than higher-order components.

Key Files in the React Repository

The facebook/react repository contains fixture files that illustrate router integration patterns:

These files show the surrounding router context. By inserting the useHistory or useNavigate hook inside any component (e.g., a custom button or a form submit handler), you can programmatically push a new entry onto the history stack, achieving the same effect as the classic history.push call.

Summary

  • React Router DOM v5 provides the useHistory hook, which returns a history object with a push method for programmatic navigation.
  • React Router DOM v6 replaces useHistory with useNavigate, offering a simpler function-based API that supports relative navigation and replace operations.
  • Always ensure your component is rendered within a <Router> provider (such as <BrowserRouter>) to access these hooks.
  • Call navigation methods inside event handlers or effects, never during the render phase, to avoid side effects.
  • Reference the facebook/react repository fixtures at fixtures/nesting/src/modern/App.js for practical integration patterns.

Frequently Asked Questions

What is the difference between useHistory and useNavigate in React Router DOM?

The useHistory hook is available in React Router DOM v5 and returns a history object containing methods like push, replace, and goBack. The useNavigate hook is the v6 replacement that returns a navigate function directly, offering a simpler API with built-in support for relative navigation and options like { replace: true }. Both serve the same fundamental purpose of enabling react router dom history push operations in functional components.

Can I use useHistory in React Router DOM v6?

No, useHistory was removed in React Router DOM v6. If you attempt to import it, you will encounter a module not found error. To migrate existing code, replace const history = useHistory() with const navigate = useNavigate(), and change history.push('/path') to navigate('/path'). The facebook/react repository fixtures demonstrate modern patterns compatible with v6.

Why do I get an error saying useNavigate cannot be used outside a Router?

This error occurs when you call the useNavigate hook (or useHistory in v5) in a component that is not a descendant of a Router provider component such as <BrowserRouter>, <HashRouter>, or <MemoryRouter>. The hook relies on React context to access the history instance. Ensure your component tree wraps the application or the specific component with the appropriate Router, as shown in the fixtures/nesting/src/modern/App.js example from the facebook/react repository.

Is it safe to call navigate during the component render phase?

No, calling navigate (or history.push) directly during the render phase is unsafe and will trigger a warning or error in React. Navigation is a side effect that should only occur in response to user interactions or explicit effect triggers. Place these calls inside event handlers (like onClick), useEffect callbacks, or other asynchronous handlers to ensure they execute outside the render cycle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →