Este posibil, la toate pentru a actualiza obiect's proprietăți cu setState?
Ceva de genul:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
Am încercat:
this.setState({jasper.name: 'someOtherName'});
și acest lucru:
this.setState({jasper: {name: 'someothername'}})
Primele rezultate într-o eroare de sintaxă și cea de-a doua nu face nimic. Orice idei?
Există mai multe moduri de a face acest lucru, din moment ce statul de actualizare este o asincron funcționare, astfel încât pentru a actualiza starea de obiect, trebuie să utilizați updater funcția cu setState
.
1 - mai Simplă:
Creați mai întâi o copie de jasper` apoi face modificări în care:
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
})
În loc de a folosi Obiectul.atribuie, de asemenea, putem scrie astfel:
let jasper = { ...prevState.jasper };
2 - Folosind [răspândirea 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
}
}))
Notă: `Obiect.atribui " și " Răspândirea Operator creează doar copie superficială, așa că, dacă ați definit imbricate obiect sau un array de obiecte, ai nevoie de o abordare diferită.
Să presupunem că ai definit statul ca:
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
Pentru a actualiza extraCheese de pizza obiect:
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
}
}
}))
Să presupunem că aveți o aplicație memento, și se gestionează datele din acest formular:
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
Pentru a actualiza starea de orice todo obiect, rula o hartă pe matrice și cec pentru o valoare unică a fiecărui obiect, în caz de condiție=true`, a reveni noul obiect cu valoare actualizată, altceva același obiect.
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
*Sugestie: Dacă obiectul nu't au o valoare unică, apoi utilizați array index.
Acest lucru este cel mai rapid și mai ușor de citit în cale:
this.setState({...this.state.jasper, name: 'someothername'});
Chiar dac acest lucru.de stat.jasper
conține deja un nume de proprietate, noul nume `nume: 'someothername' cu fi folosit.
Am folosit această soluție.
Dacă aveți un imbricate stat astfel:
acest lucru.de stat = { formInputs:{ friendName:{ valoarea:'', isValid:fals, errorMsg:'' }, friendEmail:{ valoarea:'', isValid:fals, errorMsg:'' } } }
puteți declara handleChange funcție care copiază starea actuală și re-atribuie cu valori schimbate
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);
}
aici html cu ascultător eveniment. Asigurați-vă că utilizați același nume folosit în stat obiect (în acest caz 'friendName')
<input type="text" onChange={this.handleChange} " name="friendName" />
Primul caz este într-adevăr o eroare de sintaxă.
Din moment ce nu pot't vedea restul de componente, l's greu pentru a vedea de ce ai're cuiburi obiecte în starea ta aici. L's nu este o idee bună să-și facă cuib obiecte în componenta statului. Încercați să setați starea inițială să fie:
this.state = {
name: 'jasper',
age: 28
}
În acest fel, dacă doriți să actualizați numele, puteți apela:
this.setState({
name: 'Sean'
});
Va realiza ceea ce ai're scopul pentru?
Pentru mai mari, mai complexe de date, magazine, mi-ar folosi ceva de genul Redux. Dar asta's mult mai avansate.
Regula generală cu componentă de stat este să-l folosească doar pentru a gestiona UI de stat de la componenta (de exemplu, active, temporizatoare, etc.)
Check out aceste referințe:
O altă opțiune: defini variabile din Jasper obiect și apoi sună o variabilă.
Răspândirea 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
}
})
Știu că există o mulțime de răspunsuri, dar am'm-a surprins nici unul dintre ei a crea o copie a noului obiect în afara de setState, și apoi pur și simplu setState({newObject}). Curat, concis și de încredere. Deci, în acest caz:
const jasper = { ...this.state.jasper, name: 'someothername' }
this.setState(prevState => ({ jasper }))
Sau pentru o proprietate dinamică (foarte util pentru forme)
const jasper = { ...asta.de stat.jasper, [VarRepresentingPropertyName]: 'noua valoare' } acest lucru.setState(prevState => ({ jasper }))
Poti incerca cu asta:
this.setState(prevState => {
prevState = JSON.parse(JSON.stringify(this.state.jasper));
prevState.name = 'someOtherName';
return {jasper: prevState}
})
sau pentru alte bunuri:
this.setState(prevState => {
prevState = JSON.parse(JSON.stringify(this.state.jasper));
prevState.age = 'someOtherAge';
return {jasper: prevState}
})
Sau puteți folosi handleChage funcția:
handleChage(event) {
const {name, value} = event.target;
this.setState(prevState => {
prevState = JSON.parse(JSON.stringify(this.state.jasper));
prevState[name] = value;
return {jasper: prevState}
})
}
și cod HTML:
<input
type={"text"}
name={"name"}
value={this.state.jasper.name}
onChange={this.handleChange}
/>
<br/>
<input
type={"text"}
name={"age"}
value={this.state.jasper.age}
onChange={this.handleChange}
/>
Puteți încerca cu acest: (Notă: numele de intrare tag === câmp de obiect) `` <input name="myField" type="text" valoare={acest.de stat.myObject.myField} onChange={acest.handleChangeInpForm}>
handleChangeInpForm = (e) => { să newObject = acest lucru.de stat.myObject; newObject[e.țintă.name] = e.țintă.valoare; acest lucru.setState({ myObject: newObject }) } ``
Simplu și dinamic.
Acest lucru va face treaba, dar ai nevoie pentru a seta toate id-urile de la părinte, părintele va indica numele obiectului, fiind id = "jasper" și numele numele element de intrare = proprietate în interiorul obiectului jasper.
handleChangeObj = ({target: { id , name , value}}) => this.setState({ [id]: { ...this.state[id] , [name]: value } });
Fără a utiliza Asincron și Așteaptă Folosi acest...
funCall(){
this.setState({...this.state.jasper, name: 'someothername'});
}
Dacă utilizați cu Asincron Și Așteaptă folosi acest...
async funCall(){
await this.setState({...this.state.jasper, name: 'someothername'});
}
De asemenea, în urma Alberto Piras soluție, dacă nu't doriți să copiați toate "de stat" obiect:
handleChange(el) {
let inputName = el.target.name;
let inputValue = el.target.value;
let jasperCopy = Object.assign({}, this.state.jasper);
jasperCopy[inputName].name = inputValue;
this.setState({jasper: jasperCopy});
}
aceasta este o altă soluție folosind n immutabe utilitate, foarte potrivit pentru profund imbricate obiecte cu ușurință, și tu nu ar trebui să pasă de mutație
this.setState(
produce(draft => {
draft.jasper.name = 'someothername
})
)