È possibile aggiornare le proprietà dell'oggetto con setState?
Qualcosa come:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
Ho provato:
this.setState({jasper.name: 'someOtherName'});
e questo:
this.setState({jasper: {name: 'someothername'}})
Il primo risulta in un errore di sintassi e il secondo non fa nulla. Qualche idea?
Ci sono diversi modi per farlo, poiché l'aggiornamento dello stato è un'operazione asincrona1, quindi per aggiornare l'oggetto stato, dobbiamo usare la funzione updater2 con setState
.
1- Il più semplice:
Prima create una copia di jasper
e poi fate le modifiche in quella:
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
})
Invece di usare Object.assign
possiamo anche scriverlo così:
let jasper = { ...prevState.jasper };
2- Usando [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
}
}))
Nota: Object.assign
e Spread Operator
creano solo una copia superficiale, quindi se avete definito oggetti annidati o array di oggetti, avete bisogno di un approccio diverso.
Supponiamo di aver definito lo stato come:
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
Per aggiornare extraCheese dell'oggetto pizza:
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
}
}
}))
Supponiamo che abbiate un'applicazione todo e che stiate gestendo i dati in questo modulo:
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
Per aggiornare lo stato di qualsiasi oggetto todo, eseguite una mappa sull'array e controllate per qualche valore unico di ogni oggetto, in caso di condizione=vero
, restituite il nuovo oggetto con il valore aggiornato, altrimenti lo stesso oggetto.
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
Suggerimento: Se l'oggetto non ha un valore unico, allora usate l'indice dell'array.
Il primo caso è effettivamente un errore di sintassi.
Dal momento che non posso vedere il resto del tuo componente, è difficile capire perché stai annidando oggetti nel tuo stato qui. Non è una buona idea annidare oggetti nello stato del componente. Prova a impostare il tuo stato iniziale:
this.state = {
name: 'jasper',
age: 28
}
In questo modo, se vuoi aggiornare il nome, puoi semplicemente chiamare:
this.setState({
name: 'Sean'
});
Questo otterrà ciò che vuoi ottenere?
Per gli archivi di dati più grandi e complessi, userei qualcosa come Redux. Ma questo è molto più avanzato.
La regola generale con lo stato del componente è di usarlo solo per gestire lo stato UI del componente (ad esempio attivo, timer, ecc.)
Guarda questi riferimenti:
Un'altra opzione: definite la vostra variabile fuori dall'oggetto Jasper e poi chiamate semplicemente una variabile.
Operatore diffuso: 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
}
})