这是我遇到的一段代码,我不确定它到底在做什么? 我感觉它好像正在改变国家 版本1:
this.state.items = [...this.state.initialItems];
现在,上面的代码是变异状态??
以上也可以写成第2版:
this.setState({
items:[...this.state.initialItems];
});
问题是版本1正在运行,但版本2不是。
那么,这里有什么问题?
我错过了什么?
...this.state.initialItems
做了什么?是扩散算子吗?
答案 0 :(得分:2)
这段代码肯定是变异状态。不要这样做:
this.state.items = [...this.state.initialItems];
是的,...
在这种情况下是一个传播运算符。
对于版本2,请确保不使用分号。
它应该只是:
this.setState({
items:[...this.state.initialItems]
});
当然,就像下面的海报所说,它是异步的,所以你不会马上看到结果。
增强1:
如果你想在状态准备好之后做一些事情,你可以添加一个回调作为setState的第二个参数。
this.setState({
items:[...this.state.initialItems]
}, ()=>{
// do stuff
}
);
增强2:
您对setState的第一个参数也可以是一个函数,正如另一个海报所提到的那样,当您访问状态时,它将是“最新鲜”的副本,而不是您创建传递给的对象时捕获的副本。 setstate这:
this.setState((stateNOW) => {
return {items:[...stateNOW.initialItems]};
}, ()=>{
// do stuff
}
);
答案 1 :(得分:1)
版本1正在改变您的状态,这是一种不好的做法。
版本2不是,无效(实际上是)的原因是对setState
的调用是asynchronous因此您将无法访问它下一行中的最新值。
如果您需要访问新的州值,可以使用:
this.setState(prevState => ({
items: [...prevState.initialItems],
}), () => {
console.log(this.state) // new state value
})
请参阅ReactJS文档中的this link,了解如何正确设置状态。
...
确实是spread syntax。
您可以使用它,例如:
将项目添加到数组
const arr = [1, 2, 3, 4]
const newArr = [...arr, 5, 6] // This will spread everything in arr and add numbers 5 and 6 to newArr
console.log('arr', arr)
console.log('newArr', newArr)
从数组中获取项目
const arr = [1,2,3,4]
const [firstItem, secondItem, ...others] = arr
console.log('firstItem:', firstItem)
console.log('secondItem:', secondItem)
console.log('others:', others)
创建新对象
const obj = {
name: 'Stack Overflow',
age: 10,
}
const newObj = {
...obj, // gets all properties from obj
age: 12, // but only change age
}
console.log('obj', obj)
console.log('newObj', newObj)
答案 2 :(得分:1)
版本1错了。但真正的问题是为什么?
state
是React中的一个特殊对象,它不会被变异。
假设您声明了一个对象:
const obj = {
label: 'doe'
value: 'foo'
}
然后,您使用
更新obj
obj.value = 'bar'
这是突变的过程,不应该使用状态变量执行它。相反,我们使用setState
作为更改状态的请求。
...
是spread syntax。
正如其他答案所提到的,您认为它不起作用的原因可能是因为状态更新是异步的。
您必须使用setState
回调或componentDidUpdate
生命周期挂钩来记录状态值。
setState(stateChange[, callback])
代码中的另一个问题是在setState中使用this.state.something
。就像我们之前提到的那样setState
是异步的,并且可以合并许多状态更新。因此,如果您错过了更新,那么使用this.state.initialItems
可能并不总能为您服务。
this.setState((prevState) => {
return {items: [...prevState.initialItems]};
});
这是使用先前状态值的正确方法。