React setState nu actualizează starea (Programare, Javascript, Reactjs, Stare, Setstate)

Viermele a intrebat.

Deci, am acest lucru:

let total = newDealersDeckTotal.reduce(function(a, b) {
  return a + b;
},
0);

console.log(total, 'tittal'); //outputs correct total
setTimeout(() => {
  this.setState({dealersOverallTotal: total});
}, 10);

console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1'); //outputs incorrect total

newDealersDeckTotal este doar o matrice de numere [1, 5, 9] e.g.totuși this.state.dealersOverallTotal nu oferă totalul corect, dar total face? Am pus chiar și o întârziere de timeout pentru a vedea dacă acest lucru a rezolvat problema.orice evident sau ar trebui să postez mai mult cod?

Comentarii

  • stackoverflow.com/a/36087156/4453045 –  > Por Assan.
  • @Assan Noroc!!! –  > Por The worm.
  • În afară de ceea ce se spune în răspunsuri, înregistrați în mod explicit valoarea stării, înainte de să apelați setState. –  > Por Felix Kling.
  • @FelixKling nu, chem this.state după Am setat-o. Eu înregistrez o variabilă înainte. nu? –  > Por Viermele.
  • Din cauza timeout-ului pe care îl aveți setState este într-adevăr executată după ce ați înregistrat starea. Cred că ceea ce ai vrut să faci în debugging a fost să pui console.log în interiorul timeout-ului, iar partea setState în afara. –  > Por Fabian Schultz.
10 răspunsuri
Fabian Schultz

setState() este de obicei asincronă, ceea ce înseamnă că în momentul în care console.log starea, aceasta nu este încă actualizată. Încercați să puneți jurnalul în callback-ul de la setState() metodei. Acesta este executat după ce schimbarea de stare este completă:

this.setState({ dealersOverallTotal: total }, () => {
  console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
}); 

Comentarii

  • În plus, OP înregistrează în mod explicit valoarea stării înainte de să apeleze setState. –  > Por Felix Kling.
  • Acest lucru funcționează și pentru mine, în trecut am folosit acest lucru: `this.setState({someVar: newValue},function(){ console.log(„force update}); ‘, dar din anumite motive nu mai era îngrijorător, când am actualizat codul așa cum am descris mai sus, a funcționat. aveți vreo idee de ce? –  > Por Jozcar.
  • @Jozcar Ar trebui să funcționeze, de asemenea, sintaxa nu era corectă (paranteze lipsă): this.setState({someVar: newValue},function(){ console.log("force update") }); –  > Por Fabian Schultz.
  • imgur.com/Ku0OjTl Vă rog să-mi spuneți ce ar trebui să fac pentru a scăpa de această problemă. –  > Por Johncy.
  • Uitasem complet de faptul că este un apel asincron și am făcut toate modificările de cod posibile, cu excepția acesteia și aici mi-ai salvat creierul de la ardere. mulțumesc – -.  > Por Hem M.
Mahesh Joshi

setState este asincronă. Puteți utiliza metoda callback pentru a obține starea actualizată.

changeHandler(event) {
    this.setState({ yourName: event.target.value }, () => 
    console.log(this.state.yourName));
 }

Dev01

Utilizarea async/await

async changeHandler(event) {
    await this.setState({ yourName: event.target.value });
    console.log(this.state.yourName);
}

Siraj Alam

În cazul cârligelor, ar trebui să utilizați useEffect hook.

const [fruit, setFruit] = useState('');

setFruit('Apple');

useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])

Comentarii

  • Minunat, funcționează cu useEffect. Dar de ce are nevoie de unul? –  > Por alex351.
  • useEffect se execută la fiecare re-redare și dacă elementele trecute în matrice sunt variabile de stare sand schimbate. Deci, atunci când fructul s-a schimbat și componenta se re-redimensionează, acel useEffect va rula. –  > Por Siraj Alam.
  • Execut setFruit și console.log fruit în afara lui useEffect, iar acesta nu se schimbă. :/ – –  > Por alex351.
Shubham Khatri

The setState() operațiune este asincronă și, prin urmare, aplicația dvs. console.log() va fi executată înainte de setState() să mute valorile și, prin urmare, să vedeți rezultatul.

Pentru a rezolva acest lucru, înregistrați valoarea în funcția callback din setState(), de exemplu:

setTimeout(() => {
    this.setState({dealersOverallTotal: total},
    function(){
       console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
    });
}, 10)

Comentarii

  • JavaScript este întotdeauna sincron. –  > Por Santosh Singh.
  • @santoshsingh aveți o concepție greșită. Apelurile API, timeout-urile, toate se întâmplă în mod asincron. –  > Por Shubham Khatri.
  • După cum ați menționat mai sus că javascript este asincron — nu este corect. Este în principal sincron, iar pentru anumite cazuri este asincron. stackoverflow.com/questions/2035645/… – –  > Por Santosh Singh.
  • @santoshsingh. Ohh asta a fost o greșeală din partea mea. Nu am format corect propoziția –  > Por Shubham Khatri.
  • o utilizare foarte inteligentă a callback-ului pentru a se asigura că starea este actualizată înainte de apelul următor! –  > Por user1204214.
Mokesh S

Setstate este asincron în react, deci pentru a vedea starea actualizată în consolă utilizați callback-ul așa cum se arată mai jos (funcția Callback se va executa după actualizarea setstate)

Metoda de mai jos este „nerecomandată”, dar pentru înțelegere, dacă mutați direct starea, puteți vedea starea actualizată în linia următoare. Repet, aceasta este „nerecomandată”.

Comentarii

  • MULȚUMESC că asta este, trebuie să setați direct variabila –  > Por notacorn.
Pravin Ghorle

doar adăugați componentDidUpdate(){} metoda în codul dvs. și va funcționa. puteți verifica ciclul de viață al react native aici:

https://images.app.goo.gl/BVRAi4ea2P4LchqJ8

Arun Gopalpuri

Am avut o problemă atunci când am setat starea react de mai multe ori (întotdeauna a folosit starea implicită). Urmând acest lucru react/github issue a funcționat pentru mine

const [state, setState] = useState({
  foo: "abc",
  bar: 123
});

// Do this!
setState(prevState => {
  return {
    ...prevState,
    foo: "def"
  };
});
setState(prevState => {
  return {
    ...prevState,
    bar: 456
  };
});

zmechanic

Am avut aceeași situație cu un cod alambicat și nimic din sugestiile existente nu a funcționat pentru mine.

Problema mea a fost că setState se întâmpla din funcția de callback, emisă de una dintre componente. Iar suspiciunea mea este că apelul se producea sincron, ceea ce a împiedicat setState să seteze starea deloc.

Pur și simplu am ceva de genul acesta:

render() {
    <Control
        ref={_ => this.control = _}
        onChange={this.handleChange}
        onUpdated={this.handleUpdate} />
}

handleChange() {
    this.control.doUpdate();
}

handleUpdate() {
    this.setState({...});
}

Modul în care a trebuit să o „rezolv” a fost să pun doUpdate() în setTimeout astfel:

handleChange() {
    setTimeout(() => { this.control.doUpdate(); }, 10);
}

Nu este ideal, dar altfel ar fi fost o refactorizare semnificativă.

Comentarii

  • Acest lucru mi-a rezolvat problema, dar am pus setState() în interiorul setTimeout() în loc de setTimeout(). Vă mulțumesc! –  > Por thargenediad.
Gus T Butt

Pe lângă faptul că ați observat natura asincronă a setState, trebuie să fiți conștienți de faptul că este posibil să aveți gestionari de evenimente concurente, unul care efectuează schimbarea de stare dorită, iar celălalt care o anulează imediat din nou. De exemplu, onClick pe o componentă al cărei părinte gestionează și el onClick. Verificați prin adăugarea de trace. Împiedicați acest lucru folosind e.stopPropagation.