React Router v6的HOC调用useNavigate提示不在Router上下文报错问题
问题根因
你这个报错的核心原因是高阶组件Auth的返回逻辑错误,提前执行了组件函数,导致useNavigate调用时还没进入Router的上下文环境:
- 你在
auth.js末尾写的是return AuthenticationCheck();,这是直接执行组件函数拿到返回值,执行时机是App组件渲染Route的element属性的时候,此时Router还没完成上下文初始化,自然拿不到Router上下文。 - 高阶组件应该返回组件本身(函数引用),而不是执行后的结果。
修复步骤
第一步:修改src/hoc/auth.js的返回逻辑
把末尾的return AuthenticationCheck();改成return AuthenticationCheck;,返回组件函数,不要直接执行。
// src/hoc/auth.js 修改后代码 import React, { useEffect } from "react"; 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(); const dispatch = useDispatch(); useEffect(()=> { dispatch(auth()).then(response => { console.log(response); if(!response.payload.isAuth){ if(option){ navigate('/login'); } } else { if(adminRoute && !response.payload.isAdmin){ navigate('/') } else { if(option === false){ navigate('/'); } } } }) },[navigate, dispatch, option, adminRoute]) // 透传props,避免原组件丢失路由参数等数据 return ( <SpecificComponent {...props}/> ) } // 返回组件函数,不直接执行 return AuthenticationCheck; }
第二步:修改src/App.js中Route的element写法
因为现在Auth返回的是组件函数,Route的element需要传入React元素,所以要用JSX语法包裹:
// src/App.js 修改后代码 import './App.css'; import { BrowserRouter as Router, Routes, Route } 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"; // 先生成HOC包裹后的组件 const AuthLandingPage = Auth(LandingPage, null); const AuthLoginPage = Auth(LoginPage, false); const AuthRegisterPage = Auth(RegisterPage, false); function App() { return ( <Router> <div> <Routes> {/* element传入JSX格式的组件 */} <Route path="/" element={<AuthLandingPage />}/> <Route path="/login" element={<AuthLoginPage />}/> <Route path="/register" element={<AuthRegisterPage />}/> </Routes> </div> </Router> ); } export default App;
额外说明
修改后补充的useEffect依赖项是为了避免React Hook警告和闭包旧值问题,删除了App.js中未使用的Link导入减少冗余。
内容的提问来源于stack exchange,提问作者Hyun
相关产品推荐
相关产品推荐

