Firestore获取当前登录用户姓名失败:显示undefined且提示用户未找到
解决Firestore无法获取登录用户name和surname字段的问题
问题根源分析
- 控制台输出
User not found!,说明Firestore的users集合中不存在与当前登录用户UID匹配的文档,或者文档路径配置错误。 - 你直接从Auth返回的
currentUser对象中取name和surname,但Auth对象本身只包含邮箱、UID等认证信息,name和surname是存在Firestore文档中的,所以会显示undefined undefined。
分步解决方案
1. 先确认Firestore数据正确性
- 登录Firebase控制台,进入Firestore数据库,检查
users集合下是否有以当前登录用户UID命名的文档 - 确认该文档内是否包含
name和surname字段,字段名要和代码中使用的完全一致(大小写敏感)
2. 分离状态管理
新增一个状态变量存储从Firestore获取的用户资料,避免和Auth用户对象混淆:
const [currentUser, setCurrentUser] = useState(null); const [userProfile, setUserProfile] = useState(null); // 新增状态
3. 修改getUserDoc函数
获取到Firestore文档数据后,更新userProfile状态:
async function getUserDoc() { if (!currentUser) { console.error("No current user!"); return; } const userRef = doc(db, "users", currentUser.uid); const userDoc = await getDoc(userRef); if (userDoc.exists()) { const userData = userDoc.data(); console.log("User data:", userData); setUserProfile(userData); // 保存Firestore用户数据到状态 } else { console.log("User not found!"); // 可选:如果文档不存在,可引导用户完善资料 } }
4. 修改UI渲染逻辑
从userProfile中获取姓名字段,处理加载状态:
<h3> {userProfile ? `${userProfile.name} ${userProfile.surname}` : '加载中...'} <br/> <span>{currentUser ? currentUser.email : ''}</span> </h3>
修改后的完整代码
import React, { useState, useEffect, useRef } from 'react'; import EditIcon from '@mui/icons-material/Edit'; import SettingsIcon from '@mui/icons-material/Settings'; import HelpIcon from '@mui/icons-material/Help'; import LogoutIcon from '@mui/icons-material/Logout'; import '../../styles/familyTree.css'; import profile_pic from '../../pages/familyTree/aaa.jpg'; import { auth, db} from '../../../firebase'; import Authentication from '../../../Authentication'; import { doc, getDoc } from "firebase/firestore"; function FamilyTree() { const [currentUser, setCurrentUser] = useState(null); const [userProfile, setUserProfile] = useState(null); // 新增用户资料状态 const [open, setOpen] = useState(false); const menu = useRef(); useEffect(() => { const handler = (e) => { if (!menu.current.contains(e.target)) { setOpen(false); } }; document.addEventListener('mousedown', handler); return () => { document.removeEventListener('mousedown', handler); }; }, []); // 补全依赖数组,避免重复绑定事件 useEffect(() => { const unsubscribe = auth.onAuthStateChanged((user) => { setCurrentUser(user); if (user) { setUserProfile(null); // 用户切换时重置资料 } }); return () => unsubscribe(); }, []); async function getUserDoc() { if (!currentUser) { console.error("No current user!"); return; } const userRef = doc(db, "users", currentUser.uid); const userDoc = await getDoc(userRef); if (userDoc.exists()) { const userData = userDoc.data(); console.log("User data:", userData); setUserProfile(userData); } else { console.log("User not found!"); } } useEffect(() => { if (currentUser) { getUserDoc(); } }, [currentUser]); return ( <div className="menu"> <div className="menu-wrapper" ref={menu}> <div className="menu-main" onClick={() => setOpen(!open)}> <img src={profile_pic} alt="profile pic"></img> </div> <div className={`dropdown ${open ? 'active' : 'inactive'}`}> <h3> {userProfile ? `${userProfile.name} ${userProfile.surname}` : '加载中...'} <br/> <span>{currentUser ? currentUser.email : ''}</span> </h3> <ul> <DropdownItem href="./manageAccount" text="Edit Profile" icon={<EditIcon />} /> <DropdownItem href="./manageAccount" text="Settings" icon={<SettingsIcon />} /> <DropdownItem href="./manageAccount" text="Help" icon={<HelpIcon />} /> <DropdownItem href="/" text="Logout" icon={<LogoutIcon />} onClick={() => { auth.signOut(); console.log(`${currentUser?.email} has been logged out`); // 添加可选链避免报错 }} /> </ul> </div> </div> </div> ); } function DropdownItem(props) { return ( <li className="dropdown-items"> {props.icon} <a href={props.href} className="items" onClick={props.onClick}> {props.text}</a> </li> ); } export default Authentication(FamilyTree);
额外优化点
- 第一个
useEffect补全了空依赖数组,避免每次渲染都重复绑定/解绑事件 - 登出时使用可选链
currentUser?.email,避免用户未登录时出现报错 - 用户切换时重置
userProfile状态,保证数据一致性
内容的提问来源于stack exchange,提问作者user20190936
相关产品推荐
相关产品推荐

