如何解决Firebase Auth与Firestore配合时的竞态问题?
问题根源
首次加载/浏览器刷新时,Firebase Auth还没完成初始化,直接读取auth.currentUser会得到undefined,导致后续无法获取用户邮箱并查询Firestore。而代码热重载时,Auth已经初始化完毕,能正常拿到用户数据,这就是出现这种时好时坏情况的根本原因。
解决办法
不要直接读取auth.currentUser,改用Firebase Auth的状态监听机制,等用户登录状态确定后再执行Firestore查询:
修改后的完整代码
import { doc, getDoc, getFirestore } from 'firebase/firestore'; import { auth, onAuthStateChanged } from '../firebase'; // 导入状态监听方法 import { useState, useEffect } from 'react'; const Main = () => { const db = getFirestore(); const [userName, setUserName] = useState(""); const getUser = async (currentUser) => { if (!currentUser) return; // 用户未登录时直接返回,避免无效查询 const userEmail = currentUser.email; const docRef = doc(db, 'useraccounts', userEmail); const docSnap = await getDoc(docRef); if (docSnap.exists()) { setUserName(docSnap.data().first); } else { console.log("未找到该用户的账户记录"); } }; useEffect(() => { // 监听用户登录状态变化 const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { // 用户已登录,执行Firestore查询 getUser(user); } else { // 用户未登录,清空用户名状态 setUserName(""); } }); // 组件卸载时取消监听,防止内存泄漏 return () => unsubscribe(); }, []); return ( <div> {userName ? `Welcome, ${userName}` : "加载中..."} </div> ); }; export default Main;
核心修改说明
- 新增
onAuthStateChanged监听用户登录状态,确保在Auth初始化完成、用户状态就绪后再执行数据查询。 - 调整
getUser函数,接收用户对象作为参数,避免依赖未就绪的auth.currentUser。 - 添加组件卸载时的监听清理逻辑,防止内存泄漏。
- 增加加载状态提示,优化用户体验。
内容的提问来源于stack exchange,提问作者LOTUSMS
相关产品推荐
相关产品推荐

