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

使用Firebase 9+Vue3时读取displayName出现未定义类型错误

Vue3 + Firebase9 访问Firestore文档数据时出现TypeError: Cannot read properties of undefined (reading 'displayName')

问题根源

  1. 响应式对象被错误覆盖
    你用let user = ref()创建了响应式变量,但在onSnapshot回调里直接执行user = {...doc.data()},这会把原来的ref响应式对象替换成普通JS对象,Vue无法追踪这个变量的变化,模板里的user始终是初始的空ref,自然访问不到displayName。

  2. auth.currentUser可能未初始化
    onMounted里直接调用auth.currentUser.uid,但此时Firebase Auth的状态可能还没完成初始化,currentUser可能是null,会先抛出潜在错误。

  3. 逻辑顺序不合理
    获取用户文档的逻辑应该放在onAuthStateChanged回调里,确保只有用户登录状态确认后,再去Firestore拉取数据。

修复后的代码

<script setup>
import Navbar from "@/components/navbar.vue";
import { onMounted, ref } from "vue";
import { getAuth, onAuthStateChanged, signOut } from "firebase/auth";
import { useRouter } from "vue-router";
import { doc, onSnapshot } from 'firebase/firestore';
import { db } from "@/main.js";

const router = useRouter();
const loggedIn = ref(false);
const user = ref({}); // 初始化空对象,避免模板首次渲染报错
let auth;

onMounted(() => {
  auth = getAuth();
  // 把获取用户数据的逻辑移到auth状态监听里
  onAuthStateChanged(auth, async (authUser) => {
    if (authUser) {
      loggedIn.value = true;
      const docRef = doc(db, 'users', authUser.uid);
      // 监听文档变化,实时更新数据
      onSnapshot(docRef, (doc) => {
        if (doc.exists()) {
          console.log(doc.data());
          // 修改ref的value属性,保持响应式
          user.value = { ...doc.data() };
        } else {
          console.log("No document exists");
        }
      });
    } else {
      loggedIn.value = false;
      user.value = {}; // 登出后清空用户数据
    }
  });
})

const handleSignOut = () => {
  signOut(auth).then(() => {
    router.push("/")
  })
}
</script>

<template>
  <navbar></navbar>
  <p>Account Page</p>

  <!-- 可以再加一层判断,确保user有数据再渲染 -->
  <div v-if="loggedIn && user.displayName">Hello, {{ user.displayName }}</div>
  <!-- 或者用可选链操作符容错 -->
  <!-- <div v-if="loggedIn">Hello, {{ user?.displayName }}</div> -->

  <button @click="handleSignOut">Sign Out</button>
</template>

额外优化建议

  • 模板里可以用可选链操作符user?.displayName,即使user为空也不会报错;
  • 初始化user为ref({})而不是空值,避免首次渲染时的undefined问题;
  • 把获取文档的逻辑放在onAuthStateChanged里,确保用户登录状态稳定后再拉取数据,避免currentUser为null的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:00:20