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

两个状态处理函数有何差异?为何表现不一致?

两个React状态更新函数的核心差异

这两个函数的核心区别在于是否遵循React状态的不可变性要求,直接导致了状态更新后的表现完全不同:

第二个函数的问题(直接修改原状态)

setEatenFoodList(prevList => {
  prevList[index].removingFade = true;
  return prevList;
})
  • 这段代码直接修改了原状态数组prevList里的元素属性,然后返回了原来的数组引用。React判断状态是否变化是基于引用对比的,因为数组引用没改,React会认为状态没有更新,大概率不会触发组件重渲染,你设置的removingFade: true可能不会在UI上体现出来。
  • 直接修改原状态是React的反模式,会导致状态突变,后续难以追踪状态变化的轨迹,还可能影响依赖该状态的其他逻辑。

第一个函数的特点(返回新数组,但仍有小瑕疵)

setEatenFoodList(prevList => {
  const newList = [];
  for (let i=0 ; i<prevList.length ; i++) {
    if (i === index){
      const editedFood = prevList[i];
      editedFood.removingFade = true;
      newList.push(editedFood)
    } else {
      newList.push(prevList[i])
    }
  }
  return newList;
})
  • 这段代码创建了一个新数组newList,把原数组的元素逐个复制进去,修改对应索引的元素属性后加入新数组,最后返回这个新数组。因为数组的引用变了,React能识别到状态变化,会触发组件重渲染,你的UI会更新。
  • 不过要注意,这个函数也不是完全符合不可变更新的要求:它直接修改了原数组里的editedFood对象的属性(因为对象是引用类型),原状态里的对象其实还是被改动了。如果要做到彻底的不可变,应该复制这个对象再修改,比如改成:
    const editedFood = {...prevList[i], removingFade: true};
    

总结

  • 第二个函数因为返回原数组引用,React不会触发重渲染,状态更新无效;
  • 第一个函数返回新数组,能触发重渲染,但修改原对象属性的做法不够严谨,建议改成复制对象的方式实现完全不可变更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:25:22