The ReactJS error “useNavigate() may be used only in the context of a Router component” occurs when you try to use the useNavigate
hook outside a <BrowserRouter>
or <HashRouter>
component. To fix this, move your <*Router>
tags to a higher level component.
This error was discovered when working on our SuperTokens tutorial. If you want to learn more about how to secure your apps without having to implement your own user management, be sure to check out that article.
A popular library for implementing frontend routing in React is react-router-dom
. It’s pretty simple to use, however, there are some rules you have to follow. One of those is making sure that all things that need to use the router occur inside the router component’s tags.
Let’s look at an example.
Problem: you’re using useNavigate outside the router
Let’s say you have a chat app that has a users page (we’re using code from our GraphQL chat app example – check it out). For some reason, you want to use a button instead of a simple link to go to the users page. Below is an example of how you’d do that:
import { Provider } from "urql";
import { urqlClient } from "./utils";
import { HashRouter, Route, Routes, Link, useNavigate } from "react-router-dom";
import MessagesPage from "./MessagesPage";
import UsersPage from "./UsersPage";
function App() {
const navigate = useNavigate();
const logIn = () => {
navigate("/users");
};
return (
<Provider value={urqlClient}>
<HashRouter>
<div id="menu">
Menu:
<Link to="/">Home</Link>
<button onClick={logIn}>Users</button>
</div>
<Routes>
<Route path="/" element={<MessagesPage />} />
<Route path="/users" element={<UsersPage />} />
</Routes>
</HashRouter>
</Provider>
);
}
export default App;
JavaScriptWe use react-router-dom
‘s built-in hook useNavigate
to send the user to a the users page when they click our button. This all looks like it should work, but if you were to compile and run this, you’d get a blank page and the following error in your dev console:
So what happened here? I’ve highlighted the problem below:
import { Provider } from "urql";
import { urqlClient } from "./utils";
import { HashRouter, Route, Routes, Link, useNavigate } from "react-router-dom";
import MessagesPage from "./MessagesPage";
import UsersPage from "./UsersPage";
function App() {
const navigate = useNavigate();
const logIn = () => {
navigate("/users");
};
return (
<Provider value={urqlClient}>
<HashRouter>
<div id="menu">
Menu:
<Link to="/">Home</Link>
<button onClick={logIn}>Users</button>
</div>
<Routes>
<Route path="/" element={<MessagesPage />} />
<Route path="/users" element={<UsersPage />} />
</Routes>
</HashRouter>
</Provider>
);
}
export default App;
JavaScriptAs the error says, you used the useNavigate
hook outside of a router. Here, we’re using the <HashRouter>
component, which is our router. We’re also trying to use useNavigate
up there at the top of our main App
component. The problem is, that’s outside of a router, which means useNavigate
doesn’t have access to the context info it needs to route you. In fact, it has no idea about any of the routes you created in the render portion of this component.
Solution: move your router tags to a higher level component
The way we fix this is simple. We just have to move the HashRouter
to a higher level. In our app, since we used create-react-app
to make it, that means putting the <HashRouter>
tags up in the index.js
file like so:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { HashRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>
);
JavaScriptNow, our entire app is covered by the <HashRouter>
context, and will function correctly:
Conclusion
In this article, we discussed what causes the ReactJS error “useNavigate() may be used only in the context of a Router component” and how to solve it. In a nutshell, your react-router-dom
router component (either <BrowserRouter>
or <HashRouter>
) needs to be at a high enough level in your component tree so that any components using router functions are contained within it.
John is a professional software engineer who has been solving problems with code for 15+ years. He has experience with full stack web development, container orchestration, mobile development, DevOps, Windows and Linux kernel development, cybersecurity, and reverse engineering. In his spare time, he’s researching the potential business applications of AI.