You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过currentUser id从Firestore获取用户数据返回null如何解决

问题核心原因

三个直接问题导致查询返回null、组件取值报错:

  1. 负责查询Firestore用户文档的useEffect依赖数组为空,仅会在Provider首次挂载时执行一次。首次执行时currentUser还是初始值null,逻辑直接return退出;后续鉴权监听拿到currentUser更新状态时,这个effect不会被重新触发,永远不会执行用户文档查询,user状态会一直停留在初始值null。
  2. Navbar组件的判断逻辑存在空值漏洞:仅判断了currentUser存在就直接访问user.identity,数据加载阶段currentUser先赋值、user还未查询完成时,会直接触发空引用报错。
  3. 原逻辑中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>
}
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:15:43