React结合Firestore获取数据后无法正确跳转页面,求修改方案
问题分析与修改方案
核心问题
你的代码无法正确跳转主要有这几个原因:
- 异步请求未完成就执行后续操作:
getAccounts是异步函数,你直接在useEffect里同步调用emailCheck和direct,这时候accountList还没被数据库的数据更新,检查逻辑拿不到真实数据。 - 邮箱存在性判断逻辑错误:
filter返回的是数组,哪怕是空数组,在if判断里也会被当作true,导致hasEmail永远被设为true。 - 状态更新异步特性未考虑:
setHasEmail是异步操作,设置完立刻调用direct,此时hasEmail还没更新,跳转逻辑用的还是初始的false。 - 未处理用户未登录的情况:
auth.currentUser可能为null(比如登录状态还没初始化),直接访问auth.currentUser.email会报错。
修改后的完整代码
import React, { useEffect, useState } from "react"; import { getDocs, collection, query, where } from "firebase/firestore"; import { auth, db } from "../firebase-config"; import { useNavigate } from "react-router-dom"; function Load() { const navigate = useNavigate(); const [hasEmail, setHasEmail] = useState(null); // 初始设为null,避免初始状态误触发跳转 const accountRef = collection(db, "accounts"); useEffect(() => { // 监听用户登录状态,确保拿到有效用户对象 const unsubscribe = auth.onAuthStateChanged(async (user) => { if (!user) { // 未登录时可自行处理,比如跳转登录页 navigate("/login"); return; } // 优化查询:只查当前用户邮箱的匹配文档,不用全量拉取所有账户 const emailQuery = query(accountRef, where("email", "==", user.email)); const queryResult = await getDocs(emailQuery); // 判断是否存在匹配的账户 setHasEmail(!queryResult.empty); }); // 组件卸载时取消登录状态监听,避免内存泄漏 return unsubscribe; }, [navigate, accountRef]); // 监听hasEmail状态变化,完成状态更新后执行跳转 useEffect(() => { if (hasEmail !== null) { navigate(hasEmail ? "/index" : "/enterdetails"); } }, [hasEmail, navigate]); return <div>加载中...</div>; } export default Load;
关键修改点说明
- 监听登录状态:用
auth.onAuthStateChanged确保用户登录状态稳定后再执行查询,避免currentUser为null的报错。 - 优化Firestore查询:使用
where条件过滤,只获取和当前用户邮箱匹配的文档,比全量拉取数据更高效。 - 正确判断存在性:通过
queryResult.empty直接判断是否有匹配结果,逻辑简洁准确,避免数组判断的坑。 - 分阶段触发跳转:单独用
useEffect监听hasEmail的变化,等状态更新完成后再跳转,确保逻辑执行顺序正确。 - 清理副作用:返回
unsubscribe函数,组件卸载时取消登录状态监听,避免内存泄漏。
内容的提问来源于stack exchange,提问作者arw_29
相关产品推荐
相关产品推荐

