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

React Context API+Firebase:解决未登录时创建空用户文档问题

解决方案:避免未登录时创建空用户文档

不用拆分回两个Provider,只需要在Firestore相关逻辑里增加address存在性判断,就能解决问题,具体改法如下:

关键改动点

  • 只有当address不为null时,才发起Firestore查询,否则跳过查询
  • 创建用户文档前,先确认address存在,避免写入null值
  • 调整依赖项和加载状态的逻辑,确保状态同步

修改后的完整代码

const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  const [signer, setSigner] = useState<ethers.Signer | null>(null);
  const [address, setAddress] = useState<string | null>(null);
  const [balance, setBalance] = useState<string | null>(null);
  // 只有address存在时才执行查询,否则返回空状态
  const [userDoc, dbLoading] = address 
    ? useCollection(
        query(
          collection(firestore, "users"),
          where("walletAddress", "==", address)
        )
      )
    : [null, false];
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [isConnected, setIsConnected] = useState<boolean>(false);

  useEffect(() => {
    // 新增address存在的判断,避免写入null
    if (address && !dbLoading && userDoc?.empty) {
      addDoc(collection(firestore, "users"), {
        walletAddress: address,
      });
    }

    setIsLoading(false);
  }, [dbLoading, address]); // 把address加入依赖项,确保地址变化时重新判断

  const connect = () => {
    setIsLoading(true);

    provider
      .listAccounts()
      .then((accounts) => {
        if (accounts.length > 0) {
          const signer = provider.getSigner(accounts[0]);
          setSigner(signer);
          signer.getAddress().then((address) => {
            setAddress(address);
          });
          signer.getBalance().then((balance) => {
            setBalance(balance.toString());
          });
          setIsConnected(true);
        }
      })
      .catch((error) => {
        console.log(error);
      })
      .finally(() => {
        // 增加finally设置isLoading为false,避免连接失败后一直处于加载状态
        setIsLoading(false);
      });
  };

  const disconnect = () => {
    setIsLoading(true);

    magic.connect
      .disconnect()
      .then(() => {
        setAddress(null);
        setBalance(null);
        setIsConnected(false);
      })
      .catch((error) => {
        console.log(error);
      })
      .finally(() => {
        setIsLoading(false);
      });
  };

  return (
    <AuthContext.Provider
      value={{
        userDoc: userDoc?.docs[0]?.data() ?? {},
        address,
        balance,
        isLoading: isLoading || dbLoading,
        isConnected,
        connect,
        disconnect,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

改动说明

  1. 查询逻辑优化:通过三元判断,只有address存在时才执行Firestore查询,未登录时不会发起无效查询,也不会触发后续的文档创建逻辑
  2. 文档创建防护:在useEffect里增加address的判断,确保只有用户已连接(address有值)且查询不到对应文档时,才创建新用户文档
  3. 加载状态修复:给connect方法增加finally,避免连接失败后页面一直处于加载状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:40:23