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;