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

React+Firebase使用useContext管理用户数据切换账号后数据不更新问题

问题根因
  • useEffect依赖项配置错误。你两个实现版本中负责监听用户数据的useEffect都使用了空依赖数组,只会在Provider首次挂载时执行一次。后续currentUser发生变化(切换账号、登出)时,不会重新触发获取新用户数据的逻辑。
  • 没有清理Firestore实时监听。你调用onSnapshot后没有返回取消监听的函数,前一个账号的实时监听会一直保留,旧数据更新时仍然会覆盖你当前的状态,导致数据错乱。
  • 没有处理用户登出的空值场景。用户登出后currentUser为null,直接读取user.uid会抛出运行时异常,导致后续逻辑中断。
修复方案

推荐直接整合逻辑到AuthContext,无需额外拆分DataContext,修复后的代码如下:

import React, { useContext, useState, useEffect } from 'react';
import { auth, storage, db } from '../firebase';

const AuthContext = React.createContext();

export function useAuth() {
  return useContext(AuthContext);
}

export function AuthProvider({ children }) {
  const [currentUser, setCurrentUser] = useState();
  const [currentUserData, setCurrentUserData] = useState();
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let unsubscribeUserDoc; // 保存用户文档监听的取消函数
    const unsubscribeAuth = auth.onAuthStateChanged((user) => {
      setCurrentUser(user);
      // 先取消之前的用户文档监听
      if (unsubscribeUserDoc) unsubscribeUserDoc();
      
      if (user) {
        // 已登录,监听当前用户的文档
        unsubscribeUserDoc = db.collection('users')
        .doc(user.uid)
        .onSnapshot((doc) => {
          setCurrentUserData(doc.data());
          setLoading(false);
        });
      } else {
        // 已登出,清空用户数据
        setCurrentUserData(null);
        setLoading(false);
      }
    });
    
    // 组件卸载时清理所有监听
    return () => {
      unsubscribeAuth();
      if (unsubscribeUserDoc) unsubscribeUserDoc();
    }
  }, []);
  
  // 你的signup、login、logout实现
  const signup = (email, password) => auth.createUserWithEmailAndPassword(email, password);
  const login = (email, password) => auth.signInWithEmailAndPassword(email, password);
  const logout = () => auth.signOut();

  const value = {
    currentUser,
    currentUserData,
    signup,
    login,
    logout,
  }
  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  );
}
拆分DataContext的修复方案

如果你要保留拆分的DataContext,只需要修改DataProvider的useEffect逻辑,添加依赖项和清理逻辑即可:

useEffect(() => {
  // 处理用户未登录的情况
  if (!currentUser) {
    setCurrentUserData(null);
    setLoading(false);
    return;
  }
  // 保存取消监听的函数
  const unsubscribe = db.collection('users')
    .doc(currentUser.uid)
    .onSnapshot((doc) => {
      setCurrentUserData(doc.data());
      setLoading(false);
    });
  // 依赖变化/组件卸载时清理监听
  return unsubscribe;
}, [currentUser]); // 添加currentUser为依赖项,用户切换时自动重新执行

修改后无需改动App.js的Provider嵌套结构,即可正常跟随账号切换更新用户数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:36:00