React使用Firebase V9开发自定义Hook时新建用户文档后username设置问题
问题根因
核心错误出在新建文档后的赋值逻辑:当判断docSnap.exists()为false时,你首次调用getDoc拿到的快照本身就没有数据,此时调用docSnap.data()返回值为undefined,自然无法正确给username状态赋值。
修复方案
推荐直接统一使用onSnapshot监听文档,该方法会自动触发首次数据拉取,后续文档新建、更新操作也会自动同步回调,不用拆分判断逻辑,代码更简洁也不会出现状态同步问题,修复后代码如下:
import { auth, firestore } from './firebase-config'; import { doc, onSnapshot, setDoc, } from '@firebase/firestore'; import { useEffect, useState } from 'react'; import { useAuthState } from 'react-firebase-hooks/auth'; // 自定义Hook:读取认证状态和用户档案文档 export function useUserData() { const [user] = useAuthState(auth); const [username, setUsername] = useState(null); useEffect(() => { let unsubscribe; if (user) { const documentRef = doc(firestore, 'users', user.uid); // 统一开启快照监听,自动同步所有文档变更 unsubscribe = onSnapshot(documentRef, async (doc) => { if (doc.exists()) { setUsername(doc.data().username); } else { // 文档不存在时新建 await setDoc(documentRef, { name: user.displayName, email: user.email, username: user.displayName, }); // 新建后无需手动赋值,onSnapshot会监听到新建的文档自动触发回调更新状态 } }); } else { setUsername(null); } return unsubscribe; }, [user]); return { user, username }; }
如果要保留原有代码结构不想调整逻辑,也可以直接在新建文档后,用写入数据库的用户名直接赋值即可:
// 原else分支修改为 else { const newUserInfo = { name: user.displayName, email: user.email, username: user.displayName, }; await setDoc(doc(firestore, 'users', user.uid), newUserInfo); setUsername(newUserInfo.username); }
内容的提问来源于stack exchange,提问作者Franco Labuschagne
相关产品推荐
相关产品推荐

