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

useContext全局更新useState变量异常:Login组件无法获取正确user值

问题原因

你遇到的问题是因为signInWithPopup完成后,立刻调用addToUsers时,AuthContext中的user还没完成更新。Firebase的onAuthStateChanged是异步回调,登录操作完成后,这个回调不会立刻执行,所以Login组件中从Context获取的user还是初始的空对象。

解决方案

方案一:直接使用登录返回的用户信息

不需要依赖Context的更新,直接从signInWithPopup的返回结果中拿到用户数据,传给addToUsers:

const googleSignIn = async() =>{
  // 获取登录结果里的用户对象
  const result = await signInWithPopup(auth, provider)
  const signedInUser = result.user;
  // 把用户对象传入addToUsers
  await addToUsers(signedInUser)
  navigate('/')
}
    
const addToUsers = async(user) =>{
  console.log(user)
  // 用传入的user操作数据库
  await setDoc(doc(db, 'users', user.uid), {
    displayName: user.displayName,
    photoURL : user.photoURL,
  })
}

方案二:监听Context中user的变化

通过useEffect监听Context里user的变化,当user更新为登录状态时,再执行addToUsers:

const Login = () => {
  const {user} = useContext(AuthContext)
  const navigate = useNavigate()
  // 标记是否已执行过数据库操作,避免重复触发
  const [addedToDb, setAddedToDb] = useState(false)

  const googleSignIn = async() =>{
    await signInWithPopup(auth, provider)
    navigate('/')
  }
    
  const addToUsers = async() =>{
    console.log(user)
    await setDoc(doc(db, 'users', user.uid), {
      displayName: user.displayName,
      photoURL : user.photoURL,
    })
    setAddedToDb(true)
  }

  // 监听user变化,当user存在且未执行过数据库操作时触发
  useEffect(() => {
    if (user?.uid && !addedToDb) {
      addToUsers()
    }
  }, [user, addedToDb])

  // ... 其余代码不变
}

额外优化:清理AuthContext中的订阅

你的AuthContext里的useEffect没有清理onAuthStateChanged的订阅,可能会导致内存泄漏,建议加上清理函数:

useEffect(() => {
  const unsub = onAuthStateChanged(auth, (user) => {
    setUser(user);
    console.log(user);
  });
  // 组件卸载时取消订阅
  return () => unsub();
}, [])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:03:02