是否有可能用 更新对象的属性setState
?
就像是:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
我努力了:
this.setState({jasper.name: 'someOtherName'});
还有这个:
this.setState({jasper: {name: 'someothername'}})
第一个导致语法错误,第二个什么也不做。有任何想法吗?
是否有可能用 更新对象的属性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- 使用传播语法:
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
andSpread Operator
只创建浅拷贝,因此如果您定义了嵌套对象或对象数组,则需要不同的方法。
假设您已将状态定义为:
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
更新披萨对象的 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
}
}
}))
假设您有一个待办事项应用程序,并且您正在以这种形式管理数据:
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
要更新任何 todo 对象的状态,请在数组上运行映射并检查每个对象的某些唯一值,如果是condition=true
,则返回具有更新值的新对象,否则返回相同的对象。
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
建议:如果对象没有唯一值,则使用数组索引。
这是最快和最易读的方式:
this.setState({...this.state.jasper, name: 'someothername'});
即使this.state.jasper
已经包含 name 属性,name: 'someothername'
也会使用新名称。
在这里使用扩展运算符和一些 ES6
this.setState({
jasper: {
...this.state.jasper,
name: 'something'
}
})
我知道这里有很多答案,但我很惊讶没有一个答案在 setState 之外创建新对象的副本,然后只是 setState({newObject})。干净、简洁、可靠。所以在这种情况下:
const jasper = { ...this.state.jasper, name: 'someothername' }
this.setState(() => ({ jasper }))
或者对于动态属性(对表单非常有用)
const jasper = { ...this.state.jasper, [VarRepresentingPropertyName]: 'new value' }
this.setState(() => ({ jasper }))
我使用了这个解决方案。
如果您有这样的嵌套状态:
this.state = {
formInputs:{
friendName:{
value:'',
isValid:false,
errorMsg:''
},
friendEmail:{
value:'',
isValid:false,
errorMsg:''
}
}
}
您可以声明 handleChange 函数来复制当前状态并使用更改的值重新分配它
handleChange(el) {
let inputName = el.target.name;
let inputValue = el.target.value;
let statusCopy = Object.assign({}, this.state);
statusCopy.formInputs[inputName].value = inputValue;
this.setState(statusCopy);
}
这里是带有事件侦听器的 html。确保使用与状态对象相同的名称(在本例中为“friendName”)
<input type="text" onChange={this.handleChange} " name="friendName" />