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

React:如何在useEffect完成角色设置前阻止页面渲染?

解决权限初始化前页面提前渲染的问题

你的问题核心是useEffect会在组件首次渲染后执行,导致页面先以默认的candidate权限渲染,之后才更新为正确权限。这里给你两种直接可行的解决方案:

方案一:同步初始化权限(推荐,适合当前场景)

因为nookies.get()是同步操作,不需要异步等待,直接在useState的初始化回调里计算正确权限,组件第一次渲染就会用最终权限,完全避免默认值的渲染。

修改后的代码:

function MyApp({ Component, pageProps }: AppProps): JSX.Element {
  // 同步计算初始权限,无需依赖useEffect
  const [role] = useState(() => {
    const auth = nookies.get()["auth"];
    if (auth) {
      const parsedUser = JSON.parse(auth) as unknown as CookieInfo;
      const { role_id } = parsedUser;
      if (role_id) {
        const current_user_role = roles.find(x => x.id === role_id)?.name || 'Candidate';
        return current_user_role.replace(' ', '').toLowerCase();
      }
    }
    // 无权限信息时用默认值
    return 'candidate';
  });

  const auth = nookies.get()["auth"];
  let userId = 0;

  if (auth) {
    const parsedUser = JSON.parse(auth);
    userId = parsedUser?.id;
  }

  return (
    <ThemeProvider theme={customTheme}>
      <Component {...pageProps} role={role} userId={userId} />
    </ThemeProvider>
  );
}

注意:原来的代码里useEffect依赖了role,会导致权限更新后重复触发useEffect,甚至可能无限循环,这个方案直接去掉了useEffect,从根源解决了问题。

方案二:添加加载状态(适合异步获取权限的场景)

如果之后权限需要异步获取(比如从接口拉取),可以通过加载状态阻止页面渲染,直到权限确定:

function MyApp({ Component, pageProps }: AppProps): JSX.Element {
  const [role, setRole] = useState<string | null>(null); // null表示未加载完成
  const auth = nookies.get()["auth"];

  useEffect(() => {
    const fetchRole = () => {
      if (auth) {
        const parsedUser = JSON.parse(auth) as unknown as CookieInfo;
        const { role_id } = parsedUser;
        if (role_id) {
          const current_user_role = roles.find(x => x.id === role_id)?.name || 'Candidate';
          const aclRole = current_user_role.replace(' ', '').toLowerCase();
          setRole(aclRole);
          return;
        }
      }
      // 无权限信息时设置默认值
      setRole('candidate');
    };

    fetchRole();
  }, [auth]); // 只依赖auth,避免无限循环

  // 权限未加载完成时,只显示加载组件
  if (role === null) {
    return <div>加载中...</div>; // 替换成你的自定义加载UI
  }

  let userId = 0;
  if (auth) {
    const parsedUser = JSON.parse(auth);
    userId = parsedUser?.id;
  }

  return (
    <ThemeProvider theme={customTheme}>
      <Component {...pageProps} role={role} userId={userId} />
    </ThemeProvider>
  );
}

这个方案通过role === null判断加载状态,在权限确定前不渲染业务页面,只显示加载提示,避免用户看到错误的权限内容。

内容的提问来源于stack exchange,提问作者Saltern

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:45:37