Is het überhaupt mogelijk om object's eigenschappen bij te werken met setState?
Zoiets als:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
Ik heb het geprobeerd:
this.setState({jasper.name: 'someOtherName'});
en dit:
this.setState({jasper: {name: 'someothername'}})
De eerste resulteert in een syntaxis fout en de tweede doet gewoon niets. Iemand een idee?
Er zijn meerdere manieren om dit te doen, omdat state update een async operatie is, dus om het state object te updaten, moeten we updater functie gebruiken met setState
.
1- De eenvoudigste:
Maak eerst een kopie van jasper
en voer dan de veranderingen daarin uit:
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
})
In plaats van Object.assign
te gebruiken kunnen we het ook zo schrijven:
let jasper = { ...prevState.jasper };
2- Met behulp van [spread operator]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
}
}))
Note: Object.assign
en Spread Operator
creëert alleen ondiepe kopie, dus als je geneste objecten of een array van objecten hebt gedefinieerd, heb je een andere aanpak nodig.
Veronderstel dat je state hebt gedefinieerd als:
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
Om extraCheese van pizza object bij te werken:
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
}
}
}))
Laten we aannemen dat je een todo app hebt, en dat je de gegevens in dit formulier beheert:
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
Om de status van een todo object bij te werken, voer een map uit op de array en controleer op een unieke waarde van elk object, in het geval van condition=true
, retourneer het nieuwe object met bijgewerkte waarde, anders hetzelfde object.
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
Suggestie: Als object geen unieke waarde heeft, gebruik dan array index.
Het eerste geval is inderdaad een syntaxisfout.
Aangezien ik de rest van je component niet kan zien, is het moeilijk te zien waarom je hier objecten in je state nest. Het is geen goed idee om objecten in component state te nesten. Probeer je initiële toestand in te stellen als:
this.state = {
name: 'jasper',
age: 28
}
Op die manier, als je de naam wilt updaten, kun je gewoon aanroepen:
this.setState({
name: 'Sean'
});
Zal dat bereiken wat je's beoogt?
Voor grotere, meer complexe data stores, zou ik iets als Redux gebruiken. Maar dat's veel geavanceerder.
De algemene regel met component state is om het alleen te gebruiken om de UI-status van de component te beheren (bijv. actief, timers, enz.)
Kijk eens naar deze referenties:
Een andere optie: definieer je variabele vanuit het Jasper object en roep dan gewoon een variabele aan.
Spreid operator: 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
}
})