通过currentUser id从Firestore获取用户数据返回null如何解决
问题核心原因
三个直接问题导致查询返回null、组件取值报错:
- 负责查询Firestore用户文档的
useEffect依赖数组为空,仅会在Provider首次挂载时执行一次。首次执行时currentUser还是初始值null,逻辑直接return退出;后续鉴权监听拿到currentUser更新状态时,这个effect不会被重新触发,永远不会执行用户文档查询,user状态会一直停留在初始值null。 - Navbar组件的判断逻辑存在空值漏洞:仅判断了
currentUser存在就直接访问user.identity,数据加载阶段currentUser先赋值、user还未查询完成时,会直接触发空引用报错。 - 原逻辑中
createUserDocumentFromAuth是异步执行,没有等待写入完成就继续后续流程,新用户首次登录时可能出现文档还未写入完成就发起查询,拿到空结果。
修复方案
- 移除独立的用户查询useEffect,将Firestore用户文档查询逻辑合并到鉴权状态监听回调中,保证鉴权状态变化时同步查询对应用户数据,同时等待用户文档创建完成后再发起查询,避免新用户查询空结果。
- 新增全局加载状态,标记用户鉴权、业务数据查询的完成状态,组件渲染时先判断加载状态,避免空引用报错。
- 所有访问
user属性的逻辑前,补充user非空判断。
修复后代码
UserContext.js
export const UserContext = createContext({ currentUser: null, setCurrentUser: () => null, user: null, setUser: () => null, loading: true }); export const UserProvider = ({children}) => { const [currentUser, setCurrentUser] = useState(null); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const unsub = onAuthStateChangedListener(async (authUser) => { setLoading(true); if (authUser) { // 等待用户文档写入完成再查询 await createUserDocumentFromAuth(authUser); const docUserRef = doc(db, "users", authUser.uid); const docSnapshot = await getDoc(docUserRef); setUser(docSnapshot.data()); } else { // 登出时清空业务用户数据 setUser(null); } setCurrentUser(authUser); setLoading(false); }); return unsub; }, []) const value = {currentUser, setCurrentUser, user, setUser, loading}; return <UserContext.Provider value={value}>{children}</UserContext.Provider> }
Navbar.js
const {currentUser, user, loading} = useContext(UserContext); const navigate = useNavigate(); // 数据加载阶段返回占位内容,避免空值报错 if (loading) { return <Nav>加载中...</Nav> } // 补充user非空判断后再访问identity属性 if (currentUser && user && user.identity === "parent") { return ( <Nav> <NavItem>{currentUser.displayName}</NavItem> <NavItem>Parent</NavItem> </Nav>) } else if (currentUser && user && user.identity === "author") { return ( <Nav> <NavItem>{currentUser.displayName}</NavItem> <NavItem>Author</NavItem> </Nav>) } // 此处补充未登录状态的导航栏渲染逻辑即可
内容的提问来源于stack exchange,提问作者Trishka1111
相关产品推荐
相关产品推荐

