Home > database >  (react router v6) "Error: useNavigate() may be used only in the context of a <Router> com
(react router v6) "Error: useNavigate() may be used only in the context of a <Router> com

Time:11-28

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();

CodePudding user response:

You can use Redirect component:

import { Redirect, useHistory} from 'react-router-dom';
...

const history = useHistory();
<Redirect
    to={{
        pathname: '/login',
        state: { from: history.location },
    }}
/>

or change location:

window.location.href = '/login';

CodePudding user response:

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.

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;
  • Related