使用 setState
更新对象属性是否有可能?
例如:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
我已经尝试过:
this.setState({jasper.name: 'someOtherName'});
以及这个:
this.setState({jasper: {name: 'someothername'}})
第一个会导致语法错误,而第二个则什么也不做。有什么想法吗?
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
和 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
}
}
}))
假设你有一个待办事项应用程序,并且你是以以下形式管理数据的:
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
condition=true
,则返回具有更新值的新对象,否则返回相同的对象。let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
建议:如果对象没有唯一值,则使用数组索引。
jasper
对象中删除其他属性。运行console.log(jasper)
,你会发现只有一个键name
,age
不再存在 :) - Mayank Shuklajasper
是一个object
,那么这种方式是正确的,不管它是否最好,可能还有其他更好的解决方案 :) - Mayank ShuklaObject.assign
和展开运算符都无法进行深拷贝。因此,你应该使用像lodash的deepCopy
等解决方案来解决这个问题。 - Alex Vasilevlet { jasper } = this.state
怎么样? - Brian Le这是最快和最易读的方式:
this.setState({...this.state.jasper, name: 'someothername'});
即使 this.state.jasper
已经包含了一个 name 属性,新的名字 name: 'someothername'
仍将被使用。
this.state.jasper
不一定包含最新的状态。最好使用带有 prevState
的符号表示。 - sinned在这里使用展开运算符和一些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 }))
使用钩子,我们可以按照以下方式完成
const [student, setStudent] = React.useState({name: 'jasper', age: 28});
setStudent((prevState) => ({
...prevState,
name: 'newName',
}));
我使用了这个解决方案。
如果您有这样一个嵌套状态:
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" />
statusCopy.formInputs[inputName] = inputValue;
- MikeyE试一下这个,应该能很好地工作
this.setState(Object.assign(this.state.jasper,{name:'someOtherName'}));
Object.assign({}, this.state.jasper, {name:'someOtherName'})
- Albiziathis.state = {
objName: {
propertyOne: "",
propertyTwo: ""
}
};
使用setState
更新状态
this.setState(prevState => ({
objName: {
...prevState.objName,
propertyOne: "Updated Value",
propertyTwo: "Updated value"
}
}));
const [state, setState] = useState({jasper: { name: 'jasper', age: 28 }})
const nameChangeHandler = () => {
setState(prevState => ({
...prevState,
prevState.jasper.name = "Anurag",
prevState.jasper.age = 28
})
)
}
这是另一种解决方案,使用immer不可变工具,非常适用于处理深度嵌套的对象,并且您不需要关心变异。
this.setState(
produce(draft => {
draft.jasper.name = 'someothername'
})
)
jasper
对象中的age
属性。 - Giorgi Moniava