React授权校验与条件渲染异常:状态不更新、菜单无法实时切换
问题分析与解决方案
问题总结
- 授权后仅
name状态可实时更新,session、role等状态需页面刷新才同步 - 依赖
session的useEffect未触发预期的状态更新 - 无法在授权完成后无需整页刷新切换页面头部菜单
核心问题分析
useCheckCookieToken钩子逻辑冗余与状态管理错误- 存在两个调用
checkCookieToken的useEffect,其中第二个依赖session,会触发循环执行风险(若session值不变则不会触发,但逻辑本身不合理) - 调用校验接口时未重置
loading为true,后续校验无法正确显示加载状态 - 校验失败或异常时未重置状态,导致旧状态残留
- 存在两个调用
- 页面组件状态依赖不完整
MainPage的useEffect仅依赖session,name变化时无法同步更新nameUser- 授权动作完成后未主动触发权限校验,导致状态未实时更新
修复方案
1. 重构useCheckCookieToken钩子
移除冗余逻辑,添加手动刷新方法,修复状态管理:
export function useCheckCookieToken() { const [session, setSession] = useState(''); const [loading, setLoading] = useState(true); const [name, setName] = useState(''); const [role, setRole] = useState(''); const checkCookieToken = useCallback(async () => { setLoading(true); // 每次校验前重置加载状态 try { const res = await fetch(`/api/checkCookie`, { method: 'GET', headers: { 'Content-Type': 'application/json' }, }); if (res.ok) { const result = await res.json(); setSession(result.user.id); setName(result.user.name); setRole(result.user.role); } else { // 校验失败时清空所有状态 setSession(''); setName(''); setRole(''); } } catch (error) { console.error(error); // 异常时清空状态 setSession(''); setName(''); setRole(''); } finally { setLoading(false); // 请求完成后关闭加载状态 } }, []); // 组件初始化时自动执行一次校验 useEffect(() => { checkCookieToken(); }, [checkCookieToken]); // 返回手动刷新方法,供授权后调用 return { session, loading, role, name, refreshTokenCheck: checkCookieToken }; }
2. 修复MainPage组件逻辑
补全状态定义,优化依赖项,添加授权后状态更新逻辑:
function MainPage() { const [auth, setAuth] = useState(false); const [nameUser, setNameUser] = useState(''); // 补全缺失的状态定义 const { session, loading, name, refreshTokenCheck } = useCheckCookieToken(); // 同步session和name状态到组件内部 useEffect(() => { if (session) { setNameUser(name); setAuth(true); } else { setAuth(false); setNameUser(''); } }, [session, name]); // 授权动作完成后调用此方法更新状态(比如登录弹窗确认后) const handleAuthSuccess = async () => { await refreshTokenCheck(); }; return ( <> {loading ? ( <div><CircularProgress /></div> ) : auth ? ( <UserBar setShowModal={setShowModal} nameUser={nameUser} setShowModalCatalog={setShowModalCatalog} setAuth={setAuth} /> ) : ( <Bar setShowModal={setShowModal} setShowModalCatalog={setShowModalCatalog} onAuthSuccess={handleAuthSuccess} // 传递授权成功回调 /> )} </> ) }
关键优化点
- 手动触发校验:授权完成后调用
refreshTokenCheck,无需刷新页面即可更新权限状态 - 完整状态依赖:
useEffect同时监听session和name,确保任一状态变化时同步组件内部状态 - loading状态修复:每次校验前重置
loading,避免状态不一致
内容的提问来源于stack exchange,提问作者XAZG Неизвестный
相关产品推荐
相关产品推荐

