React结合Firebase获取用户文档:刷新报错与数据获取失败问题
问题分析与解决方案
你遇到的问题核心是Firebase Auth的初始化是异步的:刷新页面时auth.currentUser和props.user都可能还没就绪,导致要么直接访问uid触发Cannot read property 'uid' of null报错,要么因为判断条件不满足无法执行数据库查询。
解决步骤
- 用
onAuthStateChanged监听用户登录状态
不要直接依赖auth.currentUser,而是用Firebase提供的onAuthStateChanged监听用户状态变化——它会在Auth初始化完成、用户登录/登出时触发回调,确保你能拿到有效的用户对象。 - 结合
props.user和Auth状态,确保用户存在再查询
同时监听props.user的变化,当props.user或Auth用户存在时,只要能拿到有效uid就执行数据库查询。 - 修复
useEffect依赖项
把props.user?.uid和auth加入依赖数组,确保状态变化时重新执行查询逻辑。
修改后的完整代码
import React, { useState, useEffect } from 'react' import { doc, collection, getDocs, query, where } from "firebase/firestore"; import { getAuth, onAuthStateChanged } from "firebase/auth"; import { db } from "../firebaseConfig.js" import { Link } from 'react-router-dom' export default function ProfilePage(props) { const [username, setUsername] = useState(""); const [name, setName] = useState("Jonah Park"); const [major, setMajor] = useState("Computer Science"); const [bio, setBio] = useState("I am a third-year CS student that loves to play volleyball and run in my free time!"); const [schedule, setSchedule] = useState([]); const [profilePicture, setProfilePicture] = useState(); const [userData, setUserData] = useState([]); const [isAuthLoaded, setIsAuthLoaded] = useState(false); // 标记Auth是否初始化完成 const shadowStyle = { boxShadow: "0px 0px 6px 0px rgba(0,0,0,0.2)" } const userCollectionRef = collection(db, "users"); const auth = getAuth(); useEffect(() => { // 监听Auth状态变化 const unsubscribe = onAuthStateChanged(auth, (user) => { setIsAuthLoaded(true); // Auth初始化完成 // 优先用props传的uid,没有则用Auth用户的uid const targetUid = props.user?.uid || user?.uid; if (targetUid) { const getUsers = async () => { let list = []; try { const q = query(userCollectionRef, where("uid", "==", targetUid)); const querySnapshot = await getDocs(q); querySnapshot.forEach((doc) => { list.push(doc.data()); }); setUserData(list); // 拿到数据后同步更新组件状态 if (list.length > 0) { setUsername(list[0].username); setName(list[0].name); setMajor(list[0].major); setBio(list[0].bio); } } catch (err) { console.log(err); } } getUsers(); } }); // 组件卸载时取消监听,避免内存泄漏 return () => unsubscribe(); }, [props.user?.uid, auth]); // 依赖props.user的uid和auth对象 // Auth未加载完成时显示加载提示 if (!isAuthLoaded) { return <div>加载中...</div>; } return ( <div style={shadowStyle}> <h1>{name}</h1> <p>用户名: {username}</p> <p>专业: {major}</p> <p>简介: {bio}</p> <Link to="/">返回首页</Link> </div> ); }
关键修改说明
- 新增
isAuthLoaded状态:标记Firebase Auth是否完成初始化,避免在Auth就绪前执行无效操作,同时给用户显示加载提示。 - 使用
onAuthStateChanged监听:解决了刷新页面时auth.currentUser为null的问题,确保在Auth状态稳定后再处理数据查询。 - 兼容双来源uid:优先使用
props.user.uid,没有则用Auth用户的uid,保证查询条件有效。 - 清理监听:组件卸载时取消Auth状态监听,避免内存泄漏。
- 数据同步更新:拿到数据库返回的用户数据后,直接同步更新组件的状态字段,无需额外逻辑。
内容的提问来源于stack exchange,提问作者Jonah Park
相关产品推荐
相关产品推荐

