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

两段React setState代码差异解析:为何后者触发重渲染前者不触发?

React状态更新不触发重渲染的原因解析

toggleOn 是一个在 onClick 事件中触发的函数。

以下是初始代码:这段代码能正常修改目标数据,但React不会将更新渲染到页面上。只有回到代码中保存后,组件才会重新渲染并展示更新后的内容。

const toggleOn = (ids) => {
  setboxData(prevBoxData => { 
    prevBoxData.map(item => {
      if(item.id === ids){
        item.on = !item.on;
      } 
      return item;
    })

    return prevBoxData;
  })
}

为什么下面这段代码能触发页面重渲染,而第一段却不行?

setboxData(prevBoxData => {
  let newData = [];
  prevBoxData.map(item => {
    if(item.id === ids){
      item.on = !item.on;
    } 
    newData.push(item);
  })

  return newData;
})

核心原因:React依赖状态的引用变化触发重渲染

React判断是否需要重渲染的逻辑是浅比较前后状态的引用:

  • 第一段代码里,你直接修改了prevBoxData数组中元素的on属性(属于直接修改原数据的变异操作),最后返回的还是原来的prevBoxData数组引用。React检测不到状态的引用变化,所以不会触发组件重渲染。
  • 第二段代码中,你创建了新的数组newData,最后返回的是这个新数组的引用。React检测到状态引用发生了改变,因此会触发组件重渲染,更新页面内容。

不过第二段代码仍有瑕疵:虽然数组是新的,但里面的元素还是原对象的引用,属于半变异操作。更规范的写法应该完全不修改原数据,返回新的对象:

const toggleOn = (ids) => {
  setboxData(prevBoxData => 
    prevBoxData.map(item => 
      item.id === ids ? {...item, on: !item.on} : item
    )
  )
}

这种写法通过扩展运算符...创建新对象,既保证了数组是新引用,目标元素也是新对象,完全遵循React不可变状态的原则。


完整React组件代码

我的完整React组件代码

const Boxes = () => {
  const [boxData, setboxData] = React.useState(Data);

  const toggleOn = (ids) => {
    setboxData(prevBoxData => { 
    
      prevBoxData.map(item => {
        if(item.id === ids){
          item.on = !item.on;
        } 
        return item;
      })

      console.table(prevBoxData);
    })
  }
  
  let boxes = boxData.map((item) => {
    console.log("Item in map: ",item)
    return(  
         <Box bData = {item} handleClick = {toggleOn} />
    )
  })
  
  return (
    <div className='box-container'>
      {boxes}
    </div>
    
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:23:18