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

如何将onAuthStateChanged内的用户UID传递到外部变量?

问题根源

你的代码核心问题是异步执行顺序错误:

  • onAuthStateChanged 是异步触发的回调函数,它不会阻塞后续代码运行。
  • 你写的 getDoc 会在 UserUid 被赋值之前就执行,所以此时 UserUid 还是初始的空字符串,自然查不到数据。
解决方案

方案1:将Firestore查询逻辑移到Auth回调内

直接把获取文档和赋值的逻辑放到 onAuthStateChanged 的回调里,确保拿到用户UID后再执行查询:

import { getDoc, doc } from 'firebase/firestore'
import { onAuthStateChanged } from 'firebase/auth'

interface DataUser {
    FullName: string;
    Email: string;
    ContactNo: string;
    CountryCode: string;
    ICNO: string;
    HomeAddress: string;
    image: string;
    userType: number;
}

// 初始化空数据,后续赋值
export let DataUser: Partial<DataUser> = {};

onAuthStateChanged(auth, async (user) => {
    if (user != null) {
        const userUid = user.uid;
        // 拿到UID后执行Firestore查询
        const docSnap = await getDoc(doc(db, "User", userUid));
        if (docSnap.exists()) {
            DataUser = {
                FullName: docSnap.data()["Name"],
                Email: docSnap.data()["Email"],
                ContactNo: docSnap.data()["Contact"],
                CountryCode: docSnap.data()["CountryCode"],
                ICNO: docSnap.data()["ICNO"],
                HomeAddress: docSnap.data()["HomeAddress"],
                image: docSnap.data()["Image"],
                userType: 0,
            };
        } else {
            console.log("用户文档不存在");
        }
    } else {
        console.log("用户未登录");
        DataUser = {};
    }
})

方案2:用Promise封装Auth状态监听(适合async/await场景)

如果希望用更清晰的async/await语法,可以把onAuthStateChanged封装成Promise:

import { getDoc, doc } from 'firebase/firestore'
import { onAuthStateChanged, User } from 'firebase/auth'

interface DataUser {
    FullName: string;
    Email: string;
    ContactNo: string;
    CountryCode: string;
    ICNO: string;
    HomeAddress: string;
    image: string;
    userType: number;
}

// 封装Auth状态监听为Promise
function waitForAuth(): Promise<User | null> {
    return new Promise((resolve) => {
        const unsubscribe = onAuthStateChanged(auth, (user) => {
            resolve(user);
            unsubscribe(); // 拿到用户后取消监听,避免重复触发
        });
    });
}

// 加载用户数据的异步函数
async function loadUserData() {
    const user = await waitForAuth();
    if (!user) {
        console.log("用户未登录");
        return null;
    }
    const docSnap = await getDoc(doc(db, "User", user.uid));
    if (!docSnap.exists()) {
        console.log("用户文档不存在");
        return null;
    }
    return {
        FullName: docSnap.data()["Name"],
        Email: docSnap.data()["Email"],
        ContactNo: docSnap.data()["Contact"],
        CountryCode: docSnap.data()["CountryCode"],
        ICNO: docSnap.data()["ICNO"],
        HomeAddress: docSnap.data()["HomeAddress"],
        image: docSnap.data()["Image"],
        userType: 0,
    } as DataUser;
}

// 导出加载函数,在需要的地方调用
export { loadUserData };

额外注意点

  1. 你之前尝试用this.UserUid报错,是因为普通函数回调里this的指向不符合预期,这里根本不需要用this,解决异步顺序问题即可。
  2. 必须处理文档不存在的情况,避免docSnap.data()!强制非空导致的运行时错误。
  3. 如果是React/Vue等框架项目,建议用框架的状态管理(比如React的useState+useEffect)存储用户数据,更符合响应式逻辑。

内容的提问来源于stack exchange,提问作者Dante How

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:28:21