我不确定自己在做正确的事,我在setState之外对变量进行了突变,对吗?还是有更优雅的方法呢?
state = {
persons: [{
name: 'jay',
age: 10
}]
}
addRow = () => {
const temp = this.state
temp.persons.push({
name: '',
age: ''
})
this.setState({
...temp
})
}
答案 0 :(得分:2)
在javascript中,对象分配是通过Referece进行的,因此,即使您在setState之外对变量进行了更改,只要您不克隆对象,它仍将引用相同的state引用。但是,如果您克隆它,则将创建一个新实例,而原始实例将不受影响
addRow = () => {
const persons = [...this.state.persons] // Clone it one level deep using spread
persons.push({
name: '',
age: ''
})
this.setState({
persons
})
}
只需使用spread syntax
和functional setState
即可完成上述操作
addRow = () => {
this.setState(prevState => ({
persons: [...prevState.persons, { name: '', age: ''}]
}))
}
尽管在您的示例中这两个动作之间似乎没有什么区别,但是您提供的初始实现中存在重大缺陷。为了了解克隆和推送之间的区别以及仅分配引用和推送之间的区别,您可以看到codesandbox demo
。
基本上,当您创建一个新组件时,如果您将状态人员作为道具传递给该组件,并且在其原始引用处进行了变异,则在componentWillReceiveProps
方法中,您会看到currentProps
和{ {1}}都是相同的,因此,如果您对子组件进行了任何检查,如果这些人的道具发生了更改,那么该组件将失败。因此,非常重要的一点是,不要根据自己的引用来更改值
没有push和spread语法,您仍然可以通过使用concat来创建原始数组的新副本来避免突变问题
nextProps
答案 1 :(得分:1)
我认为,更优雅的方法是使用功能setState
:
const newPerson = { name: '', age: -1 };
this.setState(prevState => ({ persons: [...prevState.persons, newPerson] })