使用react-router-dom时如何在App.js的useEffect中实现路由切换触发getUser鉴权
问题根因
你当前的代码仅在App组件挂载、useEffect首次执行时调用了一次getUser,后续路由切换时仅触发history.listen回调内的日志打印逻辑,getUser并没有放在路由变更的监听回调中,所以不会执行。
修复方案
调整App.js内的useEffect逻辑,将getUser放入路由监听回调中,同时补充清理逻辑避免内存泄漏:
const history = useHistory(); const { getUser } = useAuth(); useEffect(() => { // 组件挂载时先执行一次校验 getUser(); // 路由变更时执行校验 const unlisten = history.listen((location) => { console.log(`You changed the page to: ${location.pathname}`); getUser(); }); // 组件卸载时取消监听 return () => unlisten(); }, [history, getUser]);
如果getUser是每次渲染都会生成的新函数,建议用useCallback包裹getUser,避免useEffect频繁重复执行。
更合理的路由鉴权实现建议
- 鉴权逻辑收敛到PrivateRoute组件:仅针对需要登录的路由做校验,无需全局监听所有路由跳转,减少不必要的接口请求。可以给PrivateRoute增加loading状态,避免校验未完成时的错误跳转,示例代码:
const Privateroute = ({ component: Component, ...rest }) => { const { isLoggedIn, getUser } = useAuth() const [authLoading, setAuthLoading] = useState(true) const location = useLocation() useEffect(() => { const verifyAuth = async () => { await getUser() setAuthLoading(false) } verifyAuth() }, [getUser, location.pathname]) if (authLoading) return <div>加载中...</div> if (isLoggedIn) return <Route {...rest} render={props => <Component {...props} />} />; return <Redirect to={{ pathname: '/login', state: { from: location.pathname } }} /> }
- 增加请求拦截器统一处理token失效:除了路由跳转时校验token,在所有业务请求发起前判断token有效性、请求返回时拦截401状态码处理登出逻辑,覆盖用户停留在当前页面很久token过期的场景。
- 完善
getUser逻辑:你当前贴出的getUser代码缺少token校验通过后的状态更新逻辑,校验成功后需要补充setIsLoggedIn(true)、setUser的相关代码,同时给异步逻辑增加try/catch捕获接口异常,避免页面崩溃。 - 状态持久化优化:可以将用户登录状态存在React上下文或者状态管理库中,避免每次都重复读取localStorage,提升性能。
内容的提问来源于stack exchange,提问作者shubham karande
相关产品推荐
相关产品推荐

