Firebase getDocs首次运行失效,跳转/profile后首次加载无法获取文档如何解决
问题根因
这个问题是身份状态初始化异步时序和数据拉取时机不对共同导致的:
- Firebase的身份认证状态初始化是异步操作,首次页面加载时你用来判断登录状态的
isLoggedIn、用来查询数据的stUser还没完成赋值,默认是空值/未登录状态,导致首次执行getDocs时stUser.uid不存在,匹配不到任何数据,也不会抛出错误。 - 刷新页面时浏览器会缓存Firebase的身份状态,状态初始化速度远快于首次冷加载,所以
stUser能在getDocs执行前完成赋值,功能就正常了。 - 你当前的路由守卫逻辑是同步判断登录状态,在身份未初始化的中间态会触发错误的重定向逻辑,进一步打乱了执行时序。
修复步骤
1. 修复路由守卫的异步判断逻辑
新增身份初始化完成状态,只有Firebase身份回调触发后再渲染路由逻辑,避免中间态错误:
import { onAuthStateChanged } from "firebase/auth"; // 路由组件内新增状态 const [authInitialized, setAuthInitialized] = useState(false); useEffect(() => { // 监听Firebase身份状态变化 const unsubscribe = onAuthStateChanged(auth, (user) => { // 同步更新你的登录状态、用户信息状态 setIsLoggedIn({ isLoggedIn: !!user }); setStUser(user || {}); // 标记身份初始化完成 setAuthInitialized(true); }); return () => unsubscribe(); }, []); // 身份未初始化时渲染加载态,不执行路由判断 if (!authInitialized) { return <div>加载中...</div> } // 原有路由逻辑保留,放在身份初始化判断之后 return ( <div> <Route exact path="/"> <Redirect to="/auth" /> </Route> {handleRoute(images)} <Route path="/auth" component={Dashboard}> {second()} </Route> <Route strict path="/profile" component={HomePage}> {first()} </Route> </div> );
2. 调整数据拉取逻辑的执行时机
把getDocs逻辑放在/profile对应HomePage组件的useEffect中,以stUser.uid作为依赖项,确保只有用户id存在时才执行数据拉取:
// HomePage组件内 import { getDocs, collection, query, where } from "firebase/firestore"; useEffect(() => { // uid不存在时直接返回不执行查询 if (!stUser?.uid) return; const fetchUserLinks = async () => { try { // 优化:直接用后端条件查询,不用拉全量数据前端过滤,性能更好 const q = query(collection(db, "links"), where("uid", "==", stUser.uid)); const querySnapshot = await getDocs(q); const links = querySnapshot.docs.map(doc => doc.id); // 这里把links更新到你的组件状态中,比如setLinks(links) } catch (e) { console.log(e); } }; fetchUserLinks(); }, [stUser?.uid]); // 依赖uid,用户身份变化时自动重新拉取数据
其他优化点
你原有代码中querySnapshot.forEach前不需要加await,该方法是同步遍历,加await没有实际作用。
内容的提问来源于stack exchange,提问作者sociolog
相关产品推荐
相关产品推荐

