Ali je sploh mogoče posodobiti lastnosti objekta s setState?
Nekaj takega:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
Poskusil sem:
this.setState({jasper.name: 'someOtherName'});
in to:
this.setState({jasper: {name: 'someothername'}})
Prvi povzroči sintaktično napako, drugi pa ne naredi ničesar. Kakšne ideje?
To lahko storimo na več načinov, saj je posodabljanje stanja asinhronizirana operacija, zato moramo za posodobitev objekta stanja uporabiti funkcijo updater s funkcijo setState
.
1- Najenostavnejši način:
Najprej ustvarite kopijo jasperja
in nato v njej izvedite spremembe:
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
})
Namesto uporabe Object.assign
ga lahko zapišemo tudi takole:
let jasper = { ...prevState.jasper };
2- Uporaba [operatorja razpršitve]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
in Spread Operator
ustvarita le plitvo kopijo, zato če imate definiran vgnezden objekt ali polje objektov, potrebujete drugačen pristop.
Predpostavimo, da ste stanje definirali kot:
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
Posodobitev extraCheese predmeta pica:
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
}
}
}))
Predpostavimo, da imate aplikacijo todo in da upravljate podatke v tem obrazcu:
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
Če želite posodobiti stanje kateregakoli objekta todo, zaženite mapo na polju in preverite, ali ima vsak objekt neko edinstveno vrednost, v primeru pogoj=true
vrnite nov objekt s posodobljeno vrednostjo, sicer pa isti objekt.
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
Predlog: Če objekt nima edinstvene vrednosti, uporabite indeks polja.
V prvem primeru gre dejansko za sintaktično napako.
Ker ne vidim preostanka vaše komponente, ne morem ugotoviti, zakaj tu gnezdite predmete v svojem stanju. Gnezdenje objektov v stanju komponente ni dobra zamisel. Poskusite nastaviti svoje začetno stanje na:
this.state = {
name: 'jasper',
age: 28
}
Tako lahko, če želite posodobiti ime, samo pokličete:
this.setState({
name: 'Sean'
});
Ali boste s tem dosegli, kar želite?
Za večja in bolj zapletena skladišča podatkov bi uporabil nekaj, kot je Redux. Toda to je veliko bolj napredno.
Splošno pravilo pri stanju komponent je, da ga uporabljaš samo za upravljanje stanja uporabniškega vmesnika komponente (npr. aktivno, časovniki itd.).
Oglejte si te reference:
Druga možnost: definirajte spremenljivko iz predmeta Jasper in nato samo pokličite spremenljivko.
Spread 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
}
})