You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React状态变量中数组扩展语法未按预期工作

问题:Firestore数据无法正确累加至React状态数组

我尝试从Firebase Firestore中获取数据并保存到React应用的状态中,代码如下:

const [firebaseOrders, setFirebaseOrders] = useState([])

useEffect(() => {
    const getOrders = async () => {
      
      const querySnapshot = await getDocs(collection(db, `users/carlos@example.com/orders`));
      querySnapshot.forEach((doc) => {
        const newOrder = doc.data()
        setFirebaseOrders([...firebaseOrders, newOrder])
      })
  }
    getOrders();
  }, [])

  console.log(firebaseOrders)

期望得到一个包含订单对象的数组,但使用扩展语法时数组并未正确累加,最终仅保留了最后一项。控制台输出如下:

[{…}]
->0 : {titles: Array(2), timestamp: nt, prices: Array(2), amount: 869.99, amount_shipping: 6.99, …}
length : 1
->[[Prototype]] : Array(0)

[{…}]
->0 : {amount: 78.29, timestamp: nt, titles: Array(2), amount_shipping: 0, prices: Array(2), …}
length : 1
->[[Prototype]] : Array(0)

我觉得自己忽略了一些基础内容,有人能帮我解决吗?


解决方案

问题核心是React状态更新的闭包特性:
在forEach循环中多次调用setFirebaseOrders时,每次引用的firebaseOrders都是组件初始渲染时的空数组(因为useEffect依赖为空,闭包捕获的是初始状态)。所以每次更新都是基于空数组添加新订单,最终只会保留最后一次添加的结果。

方法1:使用函数式状态更新

React允许状态更新函数接收一个回调,回调参数是当前最新的状态,确保每次更新都基于最新数组:

const [firebaseOrders, setFirebaseOrders] = useState([])

useEffect(() => {
    const getOrders = async () => {
      const querySnapshot = await getDocs(collection(db, `users/carlos@example.com/orders`));
      querySnapshot.forEach((doc) => {
        const newOrder = doc.data()
        // 基于最新状态累加
        setFirebaseOrders(prevOrders => [...prevOrders, newOrder])
      })
  }
    getOrders();
  }, [])

方法2:一次性收集所有订单再更新

更高效的方式是先把所有订单数据收集到临时数组,再一次性更新状态,减少状态更新次数:

const [firebaseOrders, setFirebaseOrders] = useState([])

useEffect(() => {
    const getOrders = async () => {
      const querySnapshot = await getDocs(collection(db, `users/carlos@example.com/orders`));
      // 一次性转换所有文档数据
      const allOrders = querySnapshot.docs.map(doc => doc.data())
      // 单次更新状态
      setFirebaseOrders(allOrders)
  }
    getOrders();
  }, [])

两种方法都能解决问题,第二种方法更推荐,因为它仅触发一次状态更新,性能更优。

内容的提问来源于stack exchange,提问作者Mick Maratta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:45:30