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

React自定义Hook监听Firestore文档时isUserLoading始终为false

问题原因及修复方案

核心问题:onSnapshot的使用方式错误

你在代码中用了await onSnapshot(...),但**onSnapshot并不是异步Promise函数**——它是同步执行的,会立即返回一个取消订阅的函数,而非Promise对象。这就导致代码不会等待快照回调触发,直接跳过进入finally块,立刻把isUserLoading设为false,所以你看到的状态始终是false。

除此之外,代码还有几个潜在问题需要修正:

  • auth.currentUser可能在组件初始化时为null(Firebase Auth初始化需要时间),直接访问uid会抛出错误
  • 没有清理onSnapshot的订阅,组件卸载时会造成内存泄漏
  • useEffect依赖数组为空,当用户登录状态变化时,不会重新触发订阅

修复后的完整代码

import { doc, onSnapshot } from 'firebase/firestore';
import { useEffect, useState } from 'react';
import { db, auth } from '../../firebase';

function useCurrentUser() {
  const [user, setUser] = useState({});
  const [isUserLoading, setIsUserLoading] = useState(true); // 初始设为true更符合加载逻辑
  const [isUserError, setIsUserError] = useState(null);

  useEffect(() => {
    let unsub = null;

    const setupUserListener = () => {
      setIsUserLoading(true);
      // 先检查用户是否已登录
      const currentUser = auth.currentUser;
      if (!currentUser) {
        setIsUserError(new Error('用户未登录'));
        setIsUserLoading(false);
        return;
      }

      const userRef = doc(db, 'users', currentUser.uid);
      // onSnapshot的错误需要通过第二个回调参数捕获,而非try/catch
      unsub = onSnapshot(
        userRef,
        (doc) => {
          setUser(doc.data());
          setIsUserLoading(false); // 拿到数据后再结束加载状态
        },
        (error) => {
          setIsUserError(error);
          setIsUserLoading(false);
        }
      );
    };

    setupUserListener();

    // 返回清理函数,组件卸载时取消Firestore监听
    return () => {
      if (unsub) unsub();
    };
  }, [auth.currentUser]); // 依赖用户状态,登录/登出时重新订阅

  return { user, isUserLoading, isUserError };
}

export default useCurrentUser;

关键修复点说明

  1. 移除await,直接使用onSnapshot,并在快照回调和错误回调中分别处理加载状态
  2. 初始将isUserLoading设为true,符合组件启动时的加载预期
  3. 增加auth.currentUser的空值检查,避免初始化时的报错
  4. 在useEffect依赖数组中加入auth.currentUser,确保用户状态变化时重新建立监听
  5. 返回取消订阅函数,清理Firestore的实时监听,防止内存泄漏
  6. 将错误处理移到onSnapshot的第二个回调参数(onSnapshot的异步错误无法被try/catch捕获)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:41:34