reactjsreact-hooksjestjsreact-routerreact-router-dom

useNavigate() may be used only in the context of a <Router> component


See my code below. I'm trying to add this button that goes back to the previous page using react-router-dom but I get the below error, and also all the components on my website disappear.

Error:

useNavigate() may be used only in the context of a component

My code:

function App() {
  const navigate = useNavigate();
  return (
    <BrowserRouter>
      <div>
      <button onClick={() => navigate(-1)}>go back</button>
        <Nav/>
        <Routes>
          <Route exact path="/" element={<Home/>}/>
          <Route exact path="/home" element={<Home/>}/>
          <Route exact path="/upcoming/:user" element={<Upcoming/>}/>
          <Route exact path="/record/:user" element={<Record/>}/>
          <Route path="*" element={<NotFound/>}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

And this is the error I got in console:

Error


Solution

  • This error throws in useNavigate. useInRouterContext will check if the component(which uses useNavigate hook) is a descendant of a <Router>. If the component is not a descendant of the <Router> component, it will throw this error.

    Here's the source code to explain why you can't use useNavigate, useLocation outside of the Router component:

    useNavigate uses useLocation underly, useLocation will get the location from LocationContext provider. If you want to get the react context, you should render the component as the descendant of a context provider. Router component use the LocationContext.Provider and NavigationContext.Provider. That's why you need to render the component as the children, so that useNavigate hook can get the context data from NavigationContext and LocationContext providers.

    Your environment is browser, so you need to use BrowserRouter. BrowserRouter is built based on Router.

    Refactor to this:

    App.jsx:

    function App() {
      const navigate = useNavigate();
      return (
          <div>
            <button onClick={() => navigate(-1)}>go back</button>
            <Nav/>
            <Routes>
              <Route exact path="/" element={<Home/>}/>
              <Route exact path="/home" element={<Home/>}/>
              <Route exact path="/upcoming/:user" element={<Upcoming/>}/>
              <Route exact path="/record/:user" element={<Record/>}/>
              <Route path="*" element={<NotFound/>}/>
            </Routes>
          </div>
      );
    }
    

    index.jsx:

    import ReactDOM from 'react-dom';
    import { BrowserRouter } from 'react-router-dom';
    import App from './App';
    
    ReactDOM.render(
      <BrowserRouter>
        <App/>
      </BrowserRouter>,
      document.getElementById('root')
    )