Last updated: Apr 6, 2024
Reading timeยท3 min
The error "useNavigate() may be used only in the context of a Router
component" occurs when we try to use the useNavigate
hook outside of the
Router context in React Router.
To solve the error, use the useNavigate
hook only within the Router
context.
Here is an example of wrapping your React app in a Router
in your index.js
file.
import {createRoot} from 'react-dom/client'; import App from './App'; import {BrowserRouter as Router} from 'react-router-dom'; const rootElement = document.getElementById('root'); const root = createRoot(rootElement); // ๐๏ธ Wrap App in Router root.render( <Router> <App /> </Router> );
Now you can use the useNavigate
hook in your App.js
file.
import React from 'react'; import { useNavigate, } from 'react-router-dom'; export default function App() { const navigate = useNavigate(); const handleClick = () => { // ๐๏ธ navigate programmatically navigate('/about'); }; return ( <div> <button onClick={handleClick}>Navigate to About</button> </div> ); }
The error occurs because the useNavigate
hook makes use of the context that
the Router
component provides, so it has to be nested inside of a Router
.
Router
component is in your index.js
file because that's the entry point of your React application.Once your entire app is wrapped with a Router
component, you can use any of
the hooks from the React Router package anywhere in your components.
The solution if you get the error while using the Jest testing library is the
same, you have to wrap the component that uses the useNavigate
hook in a
Router
.
import {render} from '@testing-library/react'; import App from './App'; import {BrowserRouter as Router} from 'react-router-dom'; // ๐๏ธ Wrap component that uses useNavigate in Router test('renders react component', async () => { render( <Router> <App /> </Router>, ); // Your tests... });
useNavigate
hook returns a function that lets us navigate programmatically, e.g. after a form is submitted.The error is caused because the component we are testing or one of its children
uses the useNavigate
hook.
The useNavigate
hook can only be used inside of a Router
component because
it makes use of the context that the Router
provides.
useNavigate
hook, you have to wrap them in a Router
when testing them.history.replace()
The parameter we passed to the navigate
function is the same as the to
prop
on a <Link to="/about">
component.
If you want to use the equivalent of the history.replace()
method, pass an
options
parameter to the navigate
function.
import {useNavigate} from 'react-router-dom'; export default function App() { const navigate = useNavigate(); const handleClick = () => { // ๐๏ธ replace set to true navigate('/about', {replace: true}); }; return ( <div> <button onClick={handleClick}>Navigate to About</button> </div> ); }
When the replace
property is set to true
on the options object, the current
entry in the history stack gets replaced with the new one.
This is useful, for example, when a user logs in - you don't want them to be able to click the back button and get back to the login page.
Or if you have a route that redirects users to a different page - you don't want users to click the back button and get redirected again.
You can also call the navigate
function with a delta to go back in the history
stack, e.g. navigate(-1)
is the same as hitting the back button.
You can learn more about the related topics by checking out the following tutorials: