切换同父级嵌套子路由时,如何触发useVerifyToken钩子执行?
解决方案
核心问题分析
你遇到两个关键问题:
useVerifyToken中用普通变量data存储校验状态,无法触发组件重渲染,导致校验结果无法同步到页面。- 依赖
window.location.href无法监听到同层级子路由切换——父路由组件InauthenticatedRoutes不会因子路由变化重新渲染,且闭包问题可能导致钩子无法捕捉到window.location.href的变化。
最优解决方案:改用 useLocation 监听路由变化
直接修改 useVerifyToken 钩子,利用 React Router 提供的 useLocation 替代 window.location.href,同时用 useState 管理校验状态:
import { useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; function useVerifyToken() { // 用 useState 管理认证状态,确保状态变化能触发组件重渲染 const [isAuthenticated, setIsAuthenticated] = useState(0); // 获取路由信息,子路由切换时 location 对象会更新 const location = useLocation(); useEffect(() => { const jwt = localStorage.getItem('access'); // 替换为你的令牌校验逻辑(示例为异步校验) const verifyToken = async () => { let isValid = 0; try { // 这里可以是调用后端接口校验,或前端解析JWT验证有效性 isValid = await yourActualVerifyLogic(jwt); } catch (err) { isValid = 0; } setIsAuthenticated(isValid); }; verifyToken(); }, [location]); // 依赖 location,路由(含子路由)变化时自动触发校验 return isAuthenticated; }
解决逻辑
useLocation会在任何路由变化(包括同层级子路由切换)时返回新的 location 对象,确保useEffect能被触发。- 用
useState存储校验状态,校验完成后会自动更新组件,让InauthenticatedRoutes能拿到最新的认证状态。
替代方案:手动触发校验(不修改钩子依赖)
如果不想改动钩子核心逻辑,可以在父路由组件中监听路由变化,手动触发校验:
- 修改
InauthenticatedRoutes组件:
import React, { useEffect, useState } from 'react' import { Route, Outlet, Navigate, useLocation } from 'react-router-dom' import { Login, SignUp } from '../pages' import useVerifyToken from '../hooks/useVerifyToken' const InauthenticatedRoutes = () => { const location = useLocation(); // 用状态变量强制触发钩子的校验逻辑 const [triggerVerify, setTriggerVerify] = useState(0); const isAuth = useVerifyToken(triggerVerify); // 路由变化时更新 triggerVerify,触发钩子校验 useEffect(() => { setTriggerVerify(prev => prev + 1); }, [location]); return !isAuth ? <Outlet /> : <Navigate to="/"/> }
- 修改
useVerifyToken钩子,添加triggerVerify作为依赖:
import React, { useEffect, useState } from 'react' function useVerifyToken(triggerVerify) { const [isAuthenticated, setIsAuthenticated] = useState(0); useEffect(() => { const jwt = localStorage.getItem('access'); // 你的令牌校验逻辑 const verifyToken = async () => { // ...校验过程 setIsAuthenticated(校验结果 ? 1 : 0); }; verifyToken(); }, [triggerVerify]) // 依赖触发变量 return isAuthenticated; }
内容的提问来源于stack exchange,提问作者Melly
相关产品推荐
相关产品推荐

