You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React授权校验与条件渲染异常:状态不更新、菜单无法实时切换

问题分析与解决方案

问题总结

  • 授权后仅name状态可实时更新,session、role等状态需页面刷新才同步
  • 依赖session的useEffect未触发预期的状态更新
  • 无法在授权完成后无需整页刷新切换页面头部菜单

核心问题分析

  1. useCheckCookieToken钩子逻辑冗余与状态管理错误
    • 存在两个调用checkCookieToken的useEffect,其中第二个依赖session,会触发循环执行风险(若session值不变则不会触发,但逻辑本身不合理)
    • 调用校验接口时未重置loading为true,后续校验无法正确显示加载状态
    • 校验失败或异常时未重置状态,导致旧状态残留
  2. 页面组件状态依赖不完整
    • 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 Неизвестный

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 13:30:33