有没有可能用setState来更新对象的属性?
比如说。
this.state = {
jasper: { name: 'jasper', age: 28 },
}
我已经试过了。
this.setState({jasper.name: 'someOtherName'});
和这个。
this.setState({jasper: {name: 'someothername'}})
第一个结果是语法错误,第二个则是什么都不做。有什么想法吗?
有多种方法,因为状态更新是一个异步操作,所以为了更新状态对象,我们需要使用updater函数与setState
。
1- 最简单的一种:
首先创建一个jasper
的副本,然后在其中进行修改。
this.setState(prevState => {
let jasper = Object.assign({}, prevState.jasper); // creating copy of state variable jasper
jasper.name = 'someothername'; // update the name property, assign a new value
return { jasper }; // return new object jasper object
})
我们也可以不使用Object.assign
,而是这样写。
let jasper = { ...prevState.jasper };
2- 使用[传播操作符]3。
this.setState(prevState => ({
jasper: { // object that we want to update
...prevState.jasper, // keep all other key-value pairs
name: 'something' // update the value of specific key
}
}))
注意: Object.assign
和Spread Operator
只创建浅层拷贝,所以如果你有定义的嵌套对象或对象阵列,你需要不同的方法。
假设你已经将状态定义为。
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
要更新pizza对象的extraCheese。
this.setState(prevState => ({
food: {
...prevState.food, // copy all other key-value pairs of food object
pizza: { // specific object of food object
...prevState.food.pizza, // copy all pizza key-value pairs
extraCheese: true // update value of specific key
}
}
}))
让我们假设你有一个todo应用,并且你在这个表单中管理数据。
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
要更新任何todo对象的状态,在数组上运行map,并检查每个对象的一些独特的值,如果condition=true
,则返回带有更新值的新对象,否则就是同一个对象。
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
建议:如果对象没有唯一值,则使用数组索引。
第一种情况确实是一个语法错误。
因为我看不到你的组件的其他部分,所以很难看出你为什么在这里的状态中嵌套对象。在组件状态中嵌套对象不是一个好主意。试着把你的初始状态设置为:。
this.state = {
name: 'jasper',
age: 28
}
这样一来,如果你想更新名称,你可以直接调用。
this.setState({
name: 'Sean'
});
这能达到你的目的吗?
对于更大、更复杂的数据存储,我会使用类似Redux的东西。但那要高级得多。
组件状态的一般规则是只用它来管理组件的UI状态(例如:激活、计时器等)。
请看这些参考资料。
另一个选择:从Jasper对象中定义你的变量,然后直接调用一个变量。
扩展运算符。ES6
this.state = { jasper: { name: 'jasper', age: 28 } }
let foo = "something that needs to be saved into state"
this.setState(prevState => ({
jasper: {
...jasper.entity,
foo
}
})