Възможно ли е изобщо да се актуализират свойствата на обекта с помощта на 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- Използване на [оператор за разпространение]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
}
}
}
За да актуализирате 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 обект, стартирайте карта върху масива и проверете за някаква уникална стойност на всеки обект, в случай че 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. Но това е много по-напреднало.
Общото правило при състоянието на компонента е да го използвате само за управление на състоянието на потребителския интерфейс на компонента (например активен, таймери и др.).
Вижте тези референции:
Друг вариант: дефинирайте променливата си от обекта 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
}
})