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

ComponentDidUpdate中prevState与this.state始终相等问题排查

状态更新后ComponentDidUpdate中prevState与currState始终相等的问题

问题代码与现象

更新状态的函数:

doChangeValue(data) {
  const dataNew = this.state.data
  dataNew[data.id] = data.value
  this.setState({ ...dataNew, [dataNew[data.id]]: data.value})
}

最初的突变写法:

const dataNew = this.state.data
dataNew[data.id] = data.value
this.setState({ data: dataNew })

ComponentDidUpdate代码:

componentDidUpdate(prevProps, prevState) {
  const prev = prevState.data
  const curr = this.state.data
  const isStateChanged = isEqual(prev, curr)
  console.log(isStateChanged);
}

现象:即便状态已改变,isStateChanged始终返回true,prev和curr始终相等。

错误原因

  1. 仍在直接突变原state对象:const dataNew = this.state.data只是把原state中data对象的引用赋值给了dataNew,并没有创建新对象。后续dataNew[data.id] = data.value直接修改了原state里的data,导致prevState.data和currState.data指向同一个对象,引用完全相同。
  2. setState的写法错误:你在setState中展开了dataNew的所有属性到state根节点,还重复添加了[dataNew[data.id]]: data.value,这完全偏离了原本要更新state.data的目标,同时因为原data对象已经被突变,即使执行了setState,新旧state中的data引用还是同一个。

修正方案

要彻底避免突变,必须先创建原data对象的浅拷贝,修改拷贝后的对象,再通过setState更新state.data字段:

方案1:使用扩展运算符创建拷贝

doChangeValue(data) {
  // 创建原data的浅拷贝,生成新对象
  const dataNew = { ...this.state.data };
  // 修改新对象的属性
  dataNew[data.id] = data.value;
  // 更新state中的data字段
  this.setState({ data: dataNew });
}

方案2:使用Object.assign创建拷贝

doChangeValue(data) {
  const dataNew = Object.assign({}, this.state.data);
  dataNew[data.id] = data.value;
  this.setState({ data: dataNew });
}

这样修改后,新的dataNew是完全独立的新对象,setState会更新state.data为这个新对象。此时在componentDidUpdate中,prevState.data是旧对象引用,currState.data是新对象引用,isEqual就能正确判断两者是否相等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:40:42