You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React项目中Firestore获取数据后列表组件无法渲染问题

问题分析与解决方案

看起来你遇到的问题是状态更新时机不对,导致组件没有在Firestore数据加载完成后重新渲染。咱们来拆解一下问题出在哪,以及怎么修复:

问题根源

你的Home组件里,setData(results)是写在onSnapshot回调函数外面的——而onSnapshot是异步执行的(Firestore需要时间去获取数据),所以当setData执行时,results还是个空数组。后续当onSnapshot拿到数据并把内容push到results后,你没有再次调用setData来通知React状态已经更新,所以组件不会重新渲染,自然列表就显示不出来。

另外还有个潜在问题:每次onSnapshot触发(比如Firestore里的数据有更新),你都会往同一个results数组里push数据,这会导致数据重复积累。

修复后的代码

setData移到onSnapshot的回调内部,并且每次都重新生成数据数组,而不是复用旧数组:

// Home.js 修改后代码
import { useState, useEffect } from 'react';
import { personalDatabaseFirestore } from '../firebase/personalConfig';
import GameList from './GameList';
import './Home.css'

export default function Home(){
  const [data, setData] = useState(null);

  useEffect(()=>{
    const ref = personalDatabaseFirestore.collection('Games');
    
    const unsub = ref.onSnapshot((snapshot)=>{
      // 每次快照都重新创建数组,避免数据重复
      const results = snapshot.docs.map(doc => ({
        ...doc.data(),
        id: doc.id
      }));
      // 在这里更新状态,通知React数据已变化
      setData(results);
    },(error)=>{
      console.log(error);
    })

    return ()=>unsub();
  },[]);

  console.log(data);
  return (
    <div className='mainpage-container'>
      {data && <GameList games={data}/>}
    </div>
  );
}

修复说明

  1. 在回调内生成新数组:用snapshot.docs.map直接生成新的数组,替代原来的forEach + push,这样每次快照更新都能拿到完整的最新数据,不会出现重复。
  2. 在回调内更新状态:当Firestore返回数据(或者数据有更新)时,立刻调用setData(results),让React知道状态已经变化,触发组件重新渲染。
  3. 移除外部的空数组setData:原来的setData(results)完全是多余的,因为此时results还没有任何数据。

这样修改后,当onSnapshot第一次获取到数据时,data状态会被更新为包含游戏信息的数组,Home组件重新渲染,GameList就能接收到正确的games数据并渲染出列表项了。

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

火山引擎 最新活动