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
useHistoryhook, which returns a history object mirroring the classichistoryAPI with methods likepush,replace, andgoBack. - React Router DOM v6: Uses the
useNavigatehook, which returns a navigate function that internally callshistory.pushorhistory.replacewhile 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.
Navigating Programmatically with useNavigate
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>fromreact-router-dombefore callinguseHistoryoruseNavigate. -
Missing dependency in package.json. Run
npm install react-router-dom@^6(or@5for legacy projects) to ensure the hook APIs are available in your application. -
Navigation during render phase. Call
pushornavigateinside 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
useHistorypattern. -
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:
-
fixtures/nesting/src/modern/App.js– Demonstrates a functional component wrapped with<BrowserRouter>and route configuration, providing the context needed for hooks likeuseHistoryoruseNavigate. -
fixtures/nesting/src/modern/HomePage.js– Example of a page component that serves as a navigation target forhistory.pushornavigatecalls. -
fixtures/nesting/src/modern/AboutPage.js– Example of a target route destination, showing how components receive navigation state when reached via programmatic history push operations.
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
useHistoryhook, which returns a history object with apushmethod for programmatic navigation. - React Router DOM v6 replaces
useHistorywithuseNavigate, 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.jsfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →