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查询报错。
具体逻辑:
- 你的
AuthContext中初始user设为{}空对象,但页面刷新后,onAuthStateChanged是异步执行的——在Firebase完成用户认证状态检查前,user会先保持初始的{},随后可能变为null(未登录)或有效用户对象。 - 当
user是{}或null时,user.uid为undefined,传递给doc()方法时,Firestore内部逻辑尝试对undefined执行indexOf操作,直接抛出你看到的报错。 - 报错会中断后续的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
相关产品推荐
相关产品推荐

