react从state中获取的数组可以直接修改吗?

如下代码感觉不合理,应该怎么写

var items = this.state.items;  
items[i].status = 'doing';  
this.setState({  
      items: items  
});  

问题出现的环境背景及自己尝试过哪些方法

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 7k
5 个回答

首先不推荐这种写法,更为推荐的是immutable的写法,比如:

var items = this.state.items;  

this.setState({  
  items: items.map(item => ({...item, ...{status: 'doing'}}))  
});  

为什么直接修改不推荐呢?

有两个原因:

1 . 性能问题

这种直接改变原有对象的方式导致react无法对其进行任何优化,因此
会有潜在的性能问题

2 . 很难定位问题

如果你用了purecomponent, 会发现状态无法直接更新。
原因在于purecomponent重写了SCU,SCU中通过直接判断state和props前后的引用差别来判断,因此会
返回false,导致render无法运行

看你继承哪个。继承component可以直接修改。继承purecomponent则不行

官方并不推荐这种方式,但是很多人都这样用
如不放心可以用immutable,或者直接获取对象数组的副本再更改

const arrayCopy = sourceArray.slice();  //获取数组的副本
const objectCopy = Object.assign({}, sourceObject); //获取对象的副本
//或者上对象扩展符...

推荐使用 lodashcloneDeep 方法,深拷贝一份新的数组,然后在新数组上更改,最后将新数组 set 回去。

const { items } = this.state
// 深拷贝,得到一个新数组
const newItems = cloneDeep(items)
// 在新数组上更改
newItems[i].status = 'doing'
this.setState({  
    items: newItems, 
})
this.setState((prevState) => {
  const nextState = prevState;
  nextState.items[i].status = 'doing';
  return nextState;
});

setState()

推荐问题