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

React Firebase认证刷新后页面空白及displayName读取问题排查

问题描述

我有一个Firebase数据库,想要在用户登录成功后提取displayName值来做问候语(比如Hello George!)。功能已经实现,但刷新页面后内容全部消失,控制台报错:index.esm2017.js:1032 Uncaught TypeError: Cannot read properties of undefined (reading 'indexOf')。请问这是不是从Firebase文档提取displayName的方式导致的问题?请帮忙解释原因,以下是我的代码:

AuthContext.js

import { createContext, useContext, useEffect, useState } from "react";
import {
  onAuthStateChanged,
  signInWithEmailAndPassword,
  signOut,
} from "firebase/auth";
import { auth } from "../utils/firebase/firebase.utils";

const UserContext = createContext();

export const AuthContextProvider = ({ children }) => {
  const [user, setUser] = useState({});

  const signIn = (email, password) =>
    signInWithEmailAndPassword(auth, email, password);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
      console.log(currentUser);
      setUser(currentUser);
    });
    return () => unsubscribe();
  }, []);

  const logOut = () => signOut(auth);

  return (
    <UserContext.Provider value={{ user, signIn, logOut }}>
      {children}
    </UserContext.Provider>
  );
};

export const UserAuth = () => {
  return useContext(UserContext);
};

WelcomePage.jsx

import React, { useState, useEffect } from "react";
import { UserAuth } from "../contexts/AuthContext";
import { db } from "../utils/firebase/firebase.utils";
import { doc, Firestore, getDoc } from "firebase/firestore";

const WelcomePage = () => {
  const [userDetails, setUserDetails] = useState({});
  const { user } = UserAuth();  

  useEffect(() => {
    const docRef = doc(db, "users", user.uid);
    const fetchData = async () => {
      try {
        const docSnap = await getDoc(docRef);
        setUserDetails(docSnap.data());
        console.log(docSnap.data());
      } catch (e) {
        console.log(e);
      }
    };
    fetchData();
  }, [user]);

  return (
    <div>
      <h1>Hello, {userDetails.displayName}!</h1>
    </div>    
  );
};

export default WelcomePage;

问题原因及解决方案

核心问题

刷新页面后报错的根本原因不是提取displayName的方式,而是页面初始化时Firebase Auth的状态还未完成加载,导致user对象状态异常,进而触发Firestore查询报错。

具体逻辑:

  1. 你的AuthContext中初始user设为{}空对象,但页面刷新后,onAuthStateChanged是异步执行的——在Firebase完成用户认证状态检查前,user会先保持初始的{},随后可能变为null(未登录)或有效用户对象。
  2. 当user是{}或null时,user.uid为undefined,传递给doc()方法时,Firestore内部逻辑尝试对undefined执行indexOf操作,直接抛出你看到的报错。
  3. 报错会中断后续的Firestore数据获取流程,导致userDetails始终为空,问候语自然消失。

修复步骤

1. 修正AuthContext的初始状态

把user的初始状态从{}改为null,更准确反映未完成认证的状态:

// AuthContext.js
const [user, setUser] = useState(null);

2. 在WelcomePage中添加用户状态判断

在执行Firestore查询前,先确认user已存在(即认证完成且用户已登录):

// WelcomePage.jsx
useEffect(() => {
  // 只有当user存在时才执行查询
  if (!user) return;

  const fetchData = async () => {
    try {
      const docRef = doc(db, "users", user.uid);
      const docSnap = await getDoc(docRef);
      if (docSnap.exists()) {
        setUserDetails(docSnap.data());
      } else {
        console.log("用户文档不存在");
      }
    } catch (e) {
      console.log(e);
    }
  };
  fetchData();
}, [user]);

3. 渲染时处理空值情况

避免userDetails.displayName为undefined时显示异常:

// WelcomePage.jsx
return (
  <div>
    <h1>Hello, {userDetails.displayName || "Guest"}!</h1>
  </div>    
);

额外优化建议

  • 可以在WelcomePage中添加加载状态,比如在数据获取过程中显示"Loading...",提升用户体验。
  • 如果用户文档不存在(比如新用户首次登录未创建文档),可以添加自动创建文档的逻辑,避免后续流程异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:40:31