React项目中PrivateRoute内组件登录后不渲染,需刷新才生效如何解决?
问题根因分析
- 你代码中的
fetch是异步请求,PrivateRoute组件渲染时请求还没返回结果,urls还是初始空数组,render函数会直接执行跳转逻辑 urls是组件内的普通临时变量,就算异步请求返回后赋值,也不会触发组件重新渲染,最新的权限列表永远不会生效- 登录成功后没有主动触发权限拉取逻辑,只有页面刷新重新渲染PrivateRoute才会重新发起请求
修复方案
推荐将权限数据存在全局状态中,登录成功后主动拉取权限存入全局,避免每次路由校验都重复发起请求,这里用React Context做示例:
- 新建权限管理Context
// AuthContext.js import { createContext, useContext, useState, useEffect } from 'react'; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [allowedUrls, setAllowedUrls] = useState([]); const [loading, setLoading] = useState(true); // 公共权限拉取方法 const fetchPermissions = async () => { setLoading(true); try { const sessionRes = await fetch('api/Common/sessionStatus'); const sessionValid = await sessionRes.json(); if (sessionValid) { const screensRes = await fetch('api/Common/getScreens'); const urls = await screensRes.json(); setAllowedUrls(urls); } else { setAllowedUrls([]); } } catch (err) { setAllowedUrls([]); } finally { setLoading(false); } }; // 页面初始化时自动拉取一次权限 useEffect(() => { fetchPermissions(); }, []); return ( <AuthContext.Provider value={{ allowedUrls, loading, fetchPermissions }}> {children} </AuthContext.Provider> ); }; export const useAuth = () => useContext(AuthContext);
- 在项目入口文件用AuthProvider包裹App组件
// index.js import { AuthProvider } from './AuthContext'; ReactDOM.render( <AuthProvider> <App /> </AuthProvider>, document.getElementById('root') );
- 登录成功后主动触发权限拉取
// Login.js 登录接口请求成功逻辑中添加 const { fetchPermissions } = useAuth(); // 登录校验通过后执行 await fetchPermissions(); // 再执行路由跳转逻辑
- 改写PrivateRoute组件,从全局取权限数据做校验
export const PrivateRoute = ({ component: Component, authed, ...rest }) => { const { allowedUrls, loading } = useAuth(); return <Route {...rest} render={props => { // 权限加载中展示加载态,避免误跳转 if (loading) return <div>权限校验中...</div>; if (allowedUrls.find(x => x === authed)) { return <Component {...props} />; } return <Redirect to={{ pathname: "/Employee/AllEmployees", state: { error: "Sorry! You don't have rights to access this page." } }} /> }} /> }
如果你的项目用了Redux等其他状态管理工具,也可以把权限列表存在全局store中,逻辑和Context方案一致
内容的提问来源于stack exchange,提问作者Wajeeha Parker
相关产品推荐
相关产品推荐

