You need to enable JavaScript to run this app. React使用Firebase查询数据更新state后组件未重新渲染问题
优惠活动
大模型
产品
解决方案
定价
更多

React使用Firebase查询数据更新state后组件未重新渲染问题

问题根源

你代码的核心问题是forEach不支持等待异步回调执行完成:

  • 你在forEach的回调里用了async/await调用getDownloadURL,但Array.prototype.forEach不会等待这些异步操作执行完毕,就会直接执行后续的setWho(filteredArray)代码
  • 调用setWho的时间点,所有图片下载地址的请求还没有返回,filteredArray此时还是空数组,所以你实际上第一次更新给state的是空数组
  • 后续异步请求完成往filteredArray里push元素属于直接修改已有数组的引用,React的state浅比较检测不到这种突变,所以不会触发重渲染
  • 你在控制台看到who有值是因为控制台打印的是数组的引用,当你展开控制台打印内容的时候,异步操作已经完成,数组已经被后续push操作修改,才会显示有3个元素,不代表setState的时候数组就有值。

修复方案

把forEach遍历换成map返回Promise数组,再用Promise.all等待所有异步操作执行完成后再更新state:

const storage = getStorage(firebaseApp);
const db = getFirestore();

function Aside() {
  const [who, setWho] = useState([])

  const whoToFollow = async () => {
    const usersRef = collection(db, "users");
    const q = query(usersRef, limit(3));
    const querySnapshot = await getDocs(q);
    const results = querySnapshot.docs.map(doc => doc.data());
    // 用Promise.all等待所有异步请求完成
    const filteredArray = await Promise.all(
      results.map(async (user) => {
        const imgPath = await getDownloadURL(ref(storage, user.profilePicture));
        return {
          uid: user.UID,
          displayName: user.displayName,
          userName: user.userName,
          profilePicture: imgPath
        };
      })
    );
    console.log('Users recieved and updating who state')
    setWho(filteredArray)
  }

  useEffect(() => {
    console.log('component did mount, calling "WhoToFollow()" function')
    whoToFollow()
  }, []);

  useEffect(() => {
    console.log('who state has been updated but nothing is being rendered?')
    console.log(who)
  }, [who]);
  
  return (
    <aside> 
      <div className='aside-head'>Search</div>
      <div className='aside-cont'>
        <div className='who-to-follow'>
          <div className='wtf-head'>
            New users to follow
          </div>
          <div className='wtf-list'>
            {who.length}
          </div>
        </div>
      </div>
    </aside>
  );
}

export default Aside;

修复后filteredArray是所有异步操作完成后生成的全新数组,state更新会触发组件正常重渲染,页面上就会显示正确的数组长度3。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 13:54:03