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

Next.js 13组件在useEffect触发前提前渲染问题解决

解决Next.js组件提前渲染问题,等待用户规则校验完成

问题核心是existingUser初始值为false,导致校验过程中直接渲染表单。要解决这个问题,需要新增状态跟踪校验是否完成,在校验期间显示加载组件,直到校验结束再决定渲染表单或跳转。

修改步骤:

  1. 新增校验状态
    添加isCheckingUser状态,初始值设为true,用来标记是否正在校验用户的规则同意状态:

    const [existingUser, setExistingUser] = useState(false);
    const [isCheckingUser, setIsCheckingUser] = useState(true); // 新增状态
    const [isChecked, setIsChecked] = useState([false, false, false, false, false]);
    
  2. 更新校验函数
    修改checkExistingUser函数,在Firestore请求完成后结束校验状态,同时处理文档不存在的异常情况:

    const checkExistingUser = async () => {
      try {
        const docRef = doc(db, "users", user);
        const docSnap = await getDoc(docRef);
        // 先判断文档是否存在,再检查rulesAccepted字段
        if (docSnap.exists() && docSnap.data().rulesAccepted === true) {
          setExistingUser(true);
        } else {
          setExistingUser(false);
        }
      } catch (error) {
        console.error("校验用户状态失败:", error);
        setExistingUser(false); // 出错时默认设为未同意规则
      } finally {
        setIsCheckingUser(false); // 无论成功失败,都结束校验状态
      }
    };
    
  3. 添加校验中加载判断
    在原有的loading判断后,新增isCheckingUser的判断,在校验过程中始终显示加载组件:

    if (loading || isCheckingUser) { // 合并Auth加载和用户校验加载状态
      return <LoadingCircle />;
    }
    

关键修改后的组件片段:

function Rules() {
  const { data: session } = useSession();
  const router = useRouter();
  const { user, loading } = useAuth();
  const [existingUser, setExistingUser] = useState(false);
  const [isCheckingUser, setIsCheckingUser] = useState(true);
  const [isChecked, setIsChecked] = useState([false, false, false, false, false]);

  const checkExistingUser = async () => {
    try {
      const docRef = doc(db, "users", user);
      const docSnap = await getDoc(docRef);
      if (docSnap.exists() && docSnap.data().rulesAccepted === true) {
        setExistingUser(true);
      } else {
        setExistingUser(false);
      }
    } catch (err) {
      console.error("获取用户数据失败:", err);
      setExistingUser(false);
    } finally {
      setIsCheckingUser(false);
    }
  };

  useEffect(() => {
    if (user) {
      checkExistingUser();
    } else {
      setIsCheckingUser(false); // 无用户时直接结束校验
    }
  }, [user]);

  // ... 其他逻辑保持不变

  if (loading || isCheckingUser) {
    return <LoadingCircle />;
  }

  // ... 原表单渲染部分不变
}

为什么之前的if(!existingUser)不生效?

因为existingUser初始值是false,在校验请求完成前它不会被更新,所以!existingUser始终为true,会直接渲染表单。新增isCheckingUser状态后,我们可以明确区分「正在校验」和「校验完成且未同意规则」两种状态,避免提前渲染表单。

内容的提问来源于stack exchange,提问作者Walid Daniel Dib

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:02:18