Skip to content
Advertisement

(react router v6) “Error: useNavigate() may be used only in the context of a component” error in hoc component

In the Router section, I try to check whether the user has access to the component using the higher order component (hoc).

Therefore, check whether the user is logged in at the hoc. At this time, an attempt to access each page may be prevented or forced to move to another page according to the response value.

In order to move to another page, we need to use the “navigate” method in the hoc component.

However, when using the navigate method, the phrase "Error: use Navigate() may be used only in the context of a <Router> component" appears.

Since hoc is used in the router, I’m going to use Navigate. I think I can do it.

Can you tell me what the problem is? What am I missing here? It’s my first time trying the backend, so please understand.

src/App.js

import './App.css';
import {
  BrowserRouter as Router,
  Routes,
  Route,
  Link
} from "react-router-dom";
import LandingPage from "./components/views/LandingPage/LandingPage";
import LoginPage from "./components/views/LoginPage/LoginPage";
import RegisterPage from "./components/views/RegisterPage/RegisterPage";
import Auth from "./hoc/auth"; //<-- this is hoc!!!!!!!!!!!!!!

function App() {
  return (
    <Router>
      <div>
        <Routes>
          <Route path="/" element={Auth(LandingPage, null)}/>
          <Route path="/login" element={Auth(LoginPage, false)}/>
          <Route path="/register" element={Auth(RegisterPage, false)}/>
        </Routes>
      </div>
    </Router>
  );
}
export default App;

src/hoc/auth.js (Auth)

import React, { useEffect } from "react";
import axios from "axios";
import {useDispatch} from "react-redux";
import {auth} from "../_actions/user_action";
import { useNavigate } from "react-router-dom";

export default function(SpecificComponent, option, adminRoute = null){
    
    function AuthenticationCheck(props){
        let navigate = useNavigate(); //<-- this doesn't work!!!!
        const dispatch = useDispatch();
        
        useEffect(()=> {
            dispatch(auth()).then(response => {
                console.log(response);
                
                if(!response.payload.isAuth){
                    if(option){
                        navigate('/login');//<-- this doesn't work!!!!
                    }
                } else {
                    if(adminRoute && !response.payload.isAdmin){navigate('/')} 
                    else { 
                        if(option === false){ navigate('/'); //<-- this doesn't work!!!!}
                    }
                }
            })
        },[])
        return (
        <SpecificComponent/>
        )
    }
    
    return AuthenticationCheck();
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import "antd/dist/antd.css";
import {Provider} from "react-redux";
import {applyMiddleware, createStore} from "redux";
import promiseMiddleware from "redux-promise";
import ReduxThunk from "redux-thunk";
import Reducer from "./_reducers";

const createStoreWithMiddleware = applyMiddleware(promiseMiddleware, ReduxThunk)(createStore);


ReactDOM.render(
    <Provider store={createStoreWithMiddleware(Reducer,
            window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
        )}>
        <App />
    </Provider>,
  document.getElementById('root')
);

reportWebVitals();

Advertisement

Answer

Update your HOC as

Note: Calling a component as Function rather than JSX Element may lead to unexpected bugs and also creates issues with the usage of Hooks.

Check out this link for more understanding about Calling as Component vs Calling As Function: https://dev.to/igor_bykov/react-calling-functional-components-as-functions-1d3l

(Goto heading What is a Component at all? )

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

function ActualComp(navigate){
  console.log(navigate)
  return <>Actual Comp</>
}

function HOC(SpecificComponent, option, adminRoute = null){
    
    function AuthenticationCheck(props){
        let navigate = useNavigate(); 
        return (
              <SpecificComponent navigate={navigate} />
        )
    }
    
    return <AuthenticationCheck />; <---- Here instead of `AuthenticationCheck()`
}

function App() {
  return (
    <div>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={HOC(ActualComp)} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement