使用@reach/router的navigate跳转后Header组件未重新渲染如何解决?
问题根因分析
- Header是全局挂载的公共组件,登录后调用
navigate跳转仅路由发生变化,Header没有经历卸载-重挂载流程,原有useEffect不会重新触发拉取最新登录状态 - 当前
useEffect依赖设置为tokenObj,且在effect内部调用setToken更新tokenObj,会导致effect重复触发,存在死循环风险 - 代码小问题:
res.json(res)写法错误,json()方法不需要传入参数,且verify请求未加credentials: 'include',无法携带登录态cookie
修复方案
方案1:监听路由变化触发状态更新(适配现有逻辑,改动最小)
在Header中引入@reach/router提供的useLocation钩子,监听路由路径变化,每次路由跳转时重新拉取登录验证状态,同时清理错误的effect依赖即可。
修改后的header.js代码:
import { useLocation, Link } from '@reach/router'; // 新增路由相关导入 const Header = () => { const [tokenObj, setToken] = useState(''); const location = useLocation(); // 获取当前路由信息 useEffect(() => { fetch('/portfolio/verify', { method: "GET", credentials: 'include' // 新增配置,携带登录态cookie }) .then((res)=>{ if(res.ok) return res.json(); // 移除多余的res参数 }) .then((jsonRes)=> { setToken(jsonRes.token || '') }); }, [location.pathname]); // 依赖改为路由路径,每次路由变化触发请求 let lastNavLink; let lastNavHref; if(tokenObj){ lastNavLink = 'Messages'; lastNavHref = '/message' } else { lastNavLink = 'Login'; lastNavHref = '/login'; } // 替换原生a标签为Link组件,避免跳转时页面刷新 return <Link to={lastNavHref}> {lastNavLink} </Link> };
方案2:全局状态管理(性能更优,避免重复请求)
如果不想每次路由跳转都调用验证接口,可以用React Context/Redux等全局状态方案管理登录态:
- 定义全局AuthContext,存储token及登录状态更新方法
- 登录成功拿到
accessToken后,直接更新Context中的token值 - Header组件直接从Context中取token判断展示内容,无需单独发起验证请求
内容的提问来源于stack exchange,提问作者PariParia
相关产品推荐
相关产品推荐

