Uncaught Error: useNavigate() may be used only in the context of a <Router> component. - What is it that I am doing wrong?

I am trying to create an authenticated route and I did the following but this throws an error saying

2Transition.js:251 Uncaught Error: useNavigate() may be used only in the context of a <Router> component.
at invariant (Transition.js:251:1)
at useNavigate (TransitionGroup.js:123:1)
at App (App.tsx:27:1)
at renderWithHooks (react-dom.development.js:17415:1)
at mountIndeterminateComponent (react-dom.development.js:22173:1)
at beginWork (react-dom.development.js:23654:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:5344:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:5393:1)
at invokeGuardedCallback (react-dom.development.js:5456:1)
at beginWork$1 (react-dom.development.js:28649:1)

What is it that I am doing wrong?

import { BrowserRouter, Routes, Route, useNavigate } from "react-router-dom";


function App() {
     const navigate = useNavigate();
     return(
           <BrowserRouter>
                 <Routes>
                        <Route
                           path={APP_ROUTES.DASHBOARD}
                            element={
                             isUserLoggedIn() ? <Dashboard /> : 
                                                <>pp{navigate(APP_ROUTES.LOGIN)}</>
                            }
                        />
                 </Routes>
          </BrowserRouter>
     )
}

What would be the best way to add a couple of authenticated routes?

3 answers

  • answered 2022-05-04 10:11 Benmax

    You are trying to use useNavigate() inside the App's component that is not inside a BrowserRouter because the BrowserRouter is inside the App's component and not around.

  • answered 2022-05-04 10:14 Squiggs.

    As the error suggests, you are using a hook in a component that isn't inside the <BrowserRouter>.

    A potential solution would be to build a ProtectedRoute component

    const ProtectedRoute = ({ children }) => {
      if (! isUserLoggedIn()) {
        return <Navigate to={APP_ROUTES.LOGIN} replace />;
      }
    
      return children;
    };
    

    and wrap your route around it:

           <Route
              path="home"
              element={
                <ProtectedRoute>
                  <Dashboard />
                </ProtectedRoute>
              }
            />
    

    Good blog post here: https://www.robinwieruch.de/react-router-private-routes/

  • answered 2022-05-04 16:20 Drew Reese

    Issue

    The App component is rendering the router that provides the routing context that the useNavigate hook needs.

    Solution

    Move BrowserRouter higher in the ReactTree so that it can provide a routing context to components below it. Wrapping App component with a router is correct if you want to use any react-router-dom hooks in the App component.

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

    ...

    import { Routes, Route, useNavigate } from "react-router-dom";
    
    function App() {
      const navigate = useNavigate();
      return (
        <Routes>
          <Route
            path={APP_ROUTES.DASHBOARD}
            element={isUserLoggedIn()
              ? <Dashboard />
              : <>pp{navigate(APP_ROUTES.LOGIN)}</>
            }
          />
        </Routes>
      );
    }
    

    Additional Question

    What would be the best way to add a couple of authenticated routes?

    See How to Create a Protected Route

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum