You need to enable JavaScript to run this app. React遍历数据库返回数据更新useState数组时触发无限重渲染报错
优惠活动
大模型
产品
解决方案
定价
更多

React遍历数据库返回数据更新useState数组时触发无限重渲染报错

问题根因

你遇到的无限重渲染错误完全是因为状态更新的时机不对,核心问题有两个:

  • 把setItems的调用直接写在了组件渲染阶段的JSX map循环里。React的渲染流程是:执行组件函数计算JSX -> 状态变化触发新的一轮渲染。你现在每次渲染执行map时,都会挨个调用setItems触发新的状态更新,新渲染启动后又会跑一遍map、又调用setItems,直接形成无限循环,最终触发React的重渲染次数保护机制。
  • 就算解决了循环问题,你现在逐条目追加数组的写法本身也拿不到正确结果:每次调用setItems([...items, doc.data().id])时,因为闭包缓存的关系,拿到的永远是旧的items值,遍历3个条目最后得到的items只会是最后一个条目的id,根本不是完整列表。
正确实现方案

对于从数据库返回的snapshots派生出的items数组,完全没必要在渲染流程中手动触发状态更新,直接采用派生计算的方式就能解决所有问题:

  1. 优先直接从snapshots计算需要的items,不需要额外的独立状态:
import { useMemo, useState, useEffect } from 'react';

const [snapshots, setSnapshots] = useState([]);
// 直接基于snapshots派生items,snapshots更新时自动重新计算
const items = useMemo(() => {
  return snapshots.map(doc => doc.data().id);
}, [snapshots]);

useEffect(()=> {
    db.collection("users").doc("4sfrRMB5ROMxXDvmVdwL").collection("basket")
     .get()
     .then((snapshot) => {
      setSnapshots(snapshot.docs);            
     }); 
}, []);

return (
  <div className="cart__items__item">
    {items.map(id => (
      <div key={id}>条目ID:{id}</div>
    ))}
  </div>
)
  1. 如果后续确实需要对items做独立修改、不能只用派生值,可以在snapshots更新完成后,在对应的effect里一次性完成items的赋值,绝对不要在渲染逻辑里调用setState:
const [snapshots, setSnapshots] = useState([]);
const [items, setItems] = useState([]);

useEffect(()=> {
    db.collection("users").doc("4sfrRMB5ROMxXDvmVdwL").collection("basket")
     .get()
     .then((snapshot) => {
      setSnapshots(snapshot.docs);            
     }); 
}, []);

// 仅在snapshots内容变化时,一次性计算并更新items
useEffect(() => {
  if (!snapshots.length) return;
  const idList = snapshots.map(doc => doc.data().id);
  setItems(idList);
}, [snapshots]);
避坑提醒
  • 组件渲染流程必须是纯函数,只能做数据计算、返回JSX,绝对不能在渲染阶段直接调用setState修改状态,这是触发无限重渲染的最常见原因。
  • 批量的状态更新要在拿到完整数据源后一次性完成,不要在循环里逐次调用setState,否则不仅会触发多次不必要的重渲染,还会因为闭包缓存拿到旧的状态值,得到错误的计算结果。

内容的提问来源于stack exchange,提问作者Mohammad Amjad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 23:24:03