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

React中如何合法在条件语句后调用Hook?解决需先获取用户ID再调用钩子的问题

问题根因

useDocumentData被放在了3个条件return分支之后,仅当用户存在、鉴权加载完成且无错误时才会被调用,不同渲染场景下Hook调用数量不一致,违反了React Hook调用规则。

方案1:拆分组件(推荐,逻辑分层清晰)

将需要使用用户数据的逻辑独立为子组件,父组件仅处理鉴权逻辑,鉴权通过后才渲染子组件,子组件内可安全调用用户相关Hook。

父组件代码

import { useAuthState } from "react-firebase-hooks/auth";
import { Redirect } from "react-router-dom";
import UserDataContent from "./UserDataContent";

function YourComponent() {
  // 加载用户状态 
  const [user, loadingAuthState, errorAuthState] = useAuthState(auth);

  // 用户状态加载中
  if(loadingAuthState) {
    return <div>加载中...</div>
  }
  // 加载出现错误
  else if(errorAuthState) {
    alert(errorAuthState);
    return <Redirect to="login"/>
  }
  // 用户不存在则跳转登录页
  else if(!user) {
    return <Redirect to="/login"/>
  }

  // 鉴权通过才渲染子组件
  return <UserDataContent user={user} />
}

子组件代码(UserDataContent.jsx)

import { useDocumentData } from "react-firebase-hooks/firestore";
import { doc } from "firebase/firestore";

function UserDataContent({ user }) {
  // Hook在组件顶层调用,此时user一定存在,符合规则
  const [value, loading, error] = useDocumentData(doc(db, "users", user.uid));

  // 处理用户数据加载逻辑
  if(loading) return <div>用户数据加载中...</div>
  if(error) return <div>数据加载出错:{error.message}</div>

  return <div>渲染用户数据:{JSON.stringify(value)}</div>
}

export default UserDataContent;

方案2:不拆分组件,利用Hook参数容错特性

react-firebase-hooks的查询类Hook支持传入无效引用,会自动暂停请求不会报错,因此可以将useDocumentData提到组件最顶层,用可选参数处理user为空的情况。

import { useAuthState } from "react-firebase-hooks/auth";
import { useDocumentData } from "react-firebase-hooks/firestore";
import { doc } from "firebase/firestore";
import { Redirect } from "react-router-dom";

function YourComponent() {
  // 所有Hook统一放在组件最顶层
  const [user, loadingAuthState, errorAuthState] = useAuthState(auth);
  // user不存在时传入undefined,Hook自动暂停请求
  const [value, loading, error] = useDocumentData(user ? doc(db, "users", user.uid) : undefined);

  // 用户状态加载中
  if(loadingAuthState) {
    return <div>加载中...</div>
  }
  // 加载出现错误
  else if(errorAuthState) {
    alert(errorAuthState);
    return <Redirect to="login"/>
  }
  // 用户不存在则跳转登录页
  else if(!user) {
    return <Redirect to="/login"/>
  }

  // 处理用户数据加载逻辑
  if(loading) return <div>用户数据加载中...</div>
  if(error) return <div>数据加载出错:{error.message}</div>

  return <div>渲染用户数据:{JSON.stringify(value)}</div>
}

两种方案都保留了用户加载阶段的「加载中」提示,符合React规范,优先推荐使用方案1,代码可维护性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 23:15:04