Waarom muteert het aanroepen van de react setState-methode de status niet onmiddellijk?

Ik lees het gedeelte Formulierenvan documentatie en heb zojuist deze code geprobeerd om het gebruik van onChangete demonstreren (JSBIN).

var React= require('react');
var ControlledForm= React.createClass({
    getInitialState: function() {
        return {
            value: "initial value"
        };
    },
    handleChange: function(event) {
        console.log(this.state.value);
        this.setState({value: event.target.value});
        console.log(this.state.value);
    },
    render: function() {
        return (
            <input type="text" value={this.state.value} onChange={this.handleChange}/>
        );
    }
});
React.render(
    <ControlledForm/>,
  document.getElementById('mount')
);

Als ik de <input/>waarde in de browser bijwerk, drukt de tweede console.login de handleChangecallback de dezelfde valueals de eerste console.log, waarom ik het resultaat van this.setState({value: event.target.value})in het kader van handleChangecallback?


Antwoord 1, autoriteit 100%

Van React’s documentatie:

setState()muteert niet onmiddellijk this.statemaar creëert een
in afwachting van een staatsovergang. Toegang krijgen tot this.statena het aanroepen van dit
methode kan mogelijk de bestaande waarde retourneren. Er is geen
garantie van synchrone werking van oproepen naar setStateen oproepen kunnen
worden gegroepeerd voor prestatieverbeteringen.

Als u wilt dat een functie wordt uitgevoerd nadat de statuswijziging heeft plaatsgevonden, geeft u deze door als een callback.

this.setState({value: event.target.value}, function () {
    console.log(this.state.value);
});

Antwoord 2, autoriteit 8%

Zoals vermeld in de React-documentatie, is er geen garantie dat setStatesynchroon wordt geactiveerd, dus uw console.logkan de status retourneren voordat deze werd bijgewerkt.

p>

Michael Parker noemt het doorgeven van een callback binnen de setState. Een andere manier om de logica na statuswijziging af te handelen, is via de levenscyclusmethode componentDidUpdate, de methode die wordt aanbevolen in React-documenten.

Over het algemeen raden we aan om in plaats daarvan componentDidUpdate() te gebruiken voor dergelijke logica.

Dit is met name handig wanneer er opeenvolgende setState‘s kunnen worden geactiveerd en u dezelfde functie wilt activeren na elke statuswijziging. In plaats van een callback toe te voegen aan elke setState, kunt u de functie in de componentDidUpdateplaatsen, indien nodig met specifieke logica erin.

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}

Antwoord 3, autoriteit 3%

Je zou kunnen proberen ES7 async/wait te gebruiken. Gebruik bijvoorbeeld uw voorbeeld:

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

Antwoord 4, autoriteit 2%

Let op de levenscyclusmethoden van reageren!

Ik heb enkele uren gewerkt om erachter te komen dat getDerivedStateFromPropsna elke setState()wordt aangeroepen.

😂


Antwoord 5

async-awaitsyntaxis werkt perfect voor zoiets als het volgende…

changeStateFunction = () => {
  // Some Worker..
  this.setState((prevState) => ({
  year: funcHandleYear(),
  month: funcHandleMonth()
}));
goNextMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}
goPrevMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}

Antwoord 6

Simpel gezegd – this.setState({data: value}) is asynchroon in
natuur, wat betekent dat het uit de oproepstapel gaat en alleen terugkomt
naar de oproepstapel, tenzij deze is opgelost.

Lees over Event Loop om een ​​duidelijk beeld te krijgen van de asynchrone aard in JS en waarom het tijd kost om te updaten –

https://medium.com/ front-end-weekly/javascript-event-loop-explained-4cd26af121d4

Vandaar –

   this.setState({data:value});
    console.log(this.state.data); // will give undefined or unupdated value

omdat het even duurt om te updaten.
Om het bovenstaande proces te bereiken –

   this.setState({data:value},function () {
     console.log(this.state.data);
    });

Antwoord 7

Toegang tot this.statena het aanroepen van de setState-methode is niet gegarandeerd dat de bijgewerkte status wordt geretourneerd vanwege de asynchrone aard van setState.

Om een ​​update te garanderen na het aanroepen van setState, zijn er twee oplossingen die u kunt nastreven.

Oplossing 1:Zoals vermeldin een van de bovenstaande antwoorden, zet u uw code in de componentDidUpdatemethode

Oplossing 2:Zoals vermeld in een anderevan de bovenstaande antwoorden, geef je spullen door als terugbellen

this.setState({value: myValue}, function () {
    this.functionThatIsExecutedWhenStateIsUpdated();
});

Het is belangrijk op te merken dat deze twee oplossingen niet duidelijk uitwisselbaar zijn. De een kan niet zomaar alle use-cases van de ander oplossen. Als algemene regel geldt dat, indien mogelijk, de beste praktijk zegt dat oplossing 1 de voorkeur heeft. Maar er zijn use-cases waarbij alleen oplossing 2 “effectiever” werkt, zoals de use case “update-mijn-view-en-post-my-data”. Deze use case gaat als volgt:

Na het toevoegen van een item, bijvoorbeeld “Schema toevoegen”, wil ik beidendat item toevoegen aan een front-endlijst en de zojuist bijgewerkte lijst onmiddellijk naar de backend posten, zoals aangetoond in onderstaand concept:
voer hier de afbeeldingsbeschrijving in

Als u geen van beide oplossingen gebruikt, d.w.z. als u dit alleen in uw code zegt:

addToItemArray = () => { 
     this.setState{{ scheduledItemsArray: newObjectListWithMax}}   
     this.postData();
}
<button className="btn btn-secondary btn-block" onClick={this.addToItemArray}>Add Shedule</button>

… u plaatst de lijst exclusiefhet item “Delivery to Max”, omdat de status niet wordt bijgewerkt wanneer u this.postData()(opnieuw, omdat het asynchroon is).

Als u oplossing 1 gebruikt, maakt u een POST nadat u elk teken in het tekstvak Schemanaam hebt ingetypt!

Er zijn ook andere manieren om tegemoet te komen aan deze use-case, maar oplossing 2 geeft het beste de bedoeling weer bij het lezen van de code.

Gezien het alomtegenwoordige karakter van deze use-case in vrijwel elke web-app, is de callback-techniek die wordt uitgelegd door Michael’s antwoordeen onmisbaar stukje code in elke toolkit voor ontwikkelaars.

Other episodes