Warum ändert der Aufruf der Methode „react setState“ den Status nicht sofort?

Lesezeit: 7 Minuten

Benutzer-Avatar
Salah Eddine Taouririt

ich lese Formen Abschnitt der Reactjs-Dokumentation und habe gerade versucht, diesen Code zu demonstrieren onChange Verwendungszweck (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')
);

Wenn ich die aktualisiere <input/> Wert im Browser, der zweite console.log innerhalb der handleChange Callback druckt das gleiche value Als der erste console.logWarum kann ich das Ergebnis nicht sehen this.setState({value: event.target.value}) im Rahmen von handleChange zurückrufen?

  • Wenn Sie Hooks verwenden, werfen Sie einen Blick auf die useState set-Methode, die Änderungen nicht sofort widerspiegelt.

    – Emil Bergeron

    13. November 2019 um 20:54 Uhr

  • React 18 hat automatisches Batching eingeführt

    – lifeisfoo

    6. April um 19:12 Uhr

Benutzer-Avatar
Michael Parker

Von React Dokumentation:

setState() mutiert nicht sofort this.state erzeugt aber einen ausstehenden Zustandsübergang. Zugriff this.state nach dem Aufruf dieser Methode kann möglicherweise der vorhandene Wert zurückgegeben werden. Es gibt keine Garantie für den synchronen Betrieb von Aufrufen setState und Aufrufe können zur Leistungssteigerung gebündelt werden.

Wenn Sie möchten, dass eine Funktion ausgeführt wird, nachdem die Statusänderung erfolgt ist, übergeben Sie sie als Callback.

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

  • Gute Antwort. Die Beobachtung, die ich machen muss, ist darauf zu achten, valueLink zu verwenden. Es funktioniert gut, wenn Sie die Eingabe nicht formatieren/maskieren müssen.

    – Dherik

    18. Dezember 2015 um 2:31 Uhr

  • Vielleicht möchten Sie auch auschecken componentDidUpdate. Es wird aufgerufen, nachdem sich der Status geändert hat.

    – Keysox

    16. Mai 2016 um 21:34 Uhr

  • Kurze Frage, wenn ich darf, ich sehe, sobald wir die Funktion übergeben, die wir als Callback an setState benötigen, hatte ich gehofft, dass die Funktion zuerst ausgeführt wird, bevor render() aufgerufen wird. Aber ich sehe, die Reihenfolge ist setState() -> render() -> setStates’ callback() . ist das normal? Was ist, wenn wir unser Rendering basierend auf den Dingen steuern möchten, die wir im Callback tun? shouldComponentUpdate?

    – Semusaboi

    2. Juni 2016 um 10:44 Uhr


  • Das Ändern des Status einer Komponente löst immer ein erneutes Rendern aus, es sei denn, es liegt ein Verhalten vor shouldComponentUpdate die etwas anderes vorschreibt. Was genau versuchen Sie in dem Rückruf zu tun, an den Sie übergeben setState dass du vor dem neu rendern rendern im Glossar erklärt auftreten willst?

    – Michael Parker

    2. Juni 2016 um 14:39 Uhr

  • …warum? Könnte das jemand begründen?

    – JackHasaTastatur

    1. September 2017 um 12:26 Uhr

Wie in der React-Dokumentation erwähnt, gibt es keine Garantie für setState wird synchron gefeuert, also Ihr console.log kann den Zustand vor der Aktualisierung zurückgeben.

Michael Parker erwähnt die Weitergabe eines Rückrufs innerhalb der setState. Eine andere Möglichkeit, die Logik nach einer Zustandsänderung zu handhaben, ist über die componentDidUpdate Lifecycle-Methode, die in React-Dokumentation empfohlene Methode.

Im Allgemeinen empfehlen wir stattdessen die Verwendung von componentDidUpdate() für eine solche Logik.

Dies ist besonders nützlich, wenn es aufeinanderfolgend sein kann setStates ausgelöst, und Sie möchten nach jeder Zustandsänderung dieselbe Funktion auslösen. Anstatt jedem einen Rückruf hinzuzufügen setStatekönnten Sie die Funktion innerhalb von platzieren componentDidUpdateggf. mit spezifischer Logik im Inneren.

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

Sie könnten versuchen, ES7 async/await zu verwenden. Zum Beispiel mit Ihrem Beispiel:

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

  • Wie unterscheidet sich Ihre Antwort von der anderen qualitativ hochwertigen Antwort?

    – Tod

    22. Oktober 2018 um 23:30 Uhr


  • Die andere Antwort bezieht sich auf die Verwendung des Callbacks in setState(). Ich dachte, ich hätte dies hier für diejenigen eingefügt, für die ein Rückruf-Anwendungsfall nicht gilt. Als ich beispielsweise selbst mit diesem Problem konfrontiert war, beinhaltete mein Anwendungsfall einen Switch-Fall im aktualisierten Zustand direkt nach dem Festlegen. Daher wurde die Verwendung von async/await der Verwendung eines Rückrufs vorgezogen.

    – kurokiiru

    24. Oktober 2018 um 7:36 Uhr

  • Wird sich dies auf die Leistung auswirken, wenn ich immer await immer verwende, wenn ich einen Status aktualisieren möchte, und dann darauf warte, dass er aktualisiert wurde? Und wenn ich mehrere await setStates in einer Kette untereinander einfüge, wird es nach jedem setState-Update gerendert? oder nach dem letzten setState-Update?

    – Marc_L

    7. Juli 2019 um 19:21 Uhr

  • setState ist asynchron, gibt aber nichts zurückAlso await wird die meiste Zeit funktionieren, aber nur zufällig, da es sich um eine Race-Condition handelt.

    – Emil Bergeron

    26. Juli 2019 um 17:10 Uhr

Achten Sie auf die Reaktionslebenszyklusmethoden!

Ich habe mehrere Stunden daran gearbeitet, das herauszufinden getDerivedStateFromProps wird nach jedem angerufen setState().

😂

async-await Syntax funktioniert perfekt für etwas wie das Folgende …

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}`);
}

Benutzer-Avatar
Dekan P

Zugriff this.state nach dem Anruf beim setState -Methode gibt aufgrund der asynchronen Natur von nicht garantiert den aktualisierten Status zurück setState.

Um ein Update nach Anruf zu garantieren setStategibt es zwei Lösungen, die Sie verfolgen können.

Lösung 1: Wie in einer der obigen Antworten erwähnt, geben Sie Ihren Code in die ein componentDidUpdate Methode

Lösung 2: Wie in einer anderen der obigen Antworten erwähnt, geben Sie Ihre Daten als Rückruf weiter

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

Es ist wichtig zu beachten, dass diese beiden Lösungen nicht eindeutig austauschbar sind. Das eine kann nicht ohne Weiteres alle Anwendungsfälle des anderen lösen. Als allgemeine Regel, wenn möglich, sagt Best Practice, dass Lösung 1 bevorzugt wird. Es gibt jedoch Anwendungsfälle, in denen nur Lösung 2 „effektiver“ funktioniert, wie z. B. der Anwendungsfall „Aktualisiere meine Ansicht und poste meine Daten“. Dieser Anwendungsfall geht so:

Nachdem Sie ein Element hinzugefügt haben, sagen Sie „Zeitplan hinzufügen“, ich möchte beide Fügen Sie dieses Element zu einer Front-End-Liste hinzu und posten Sie die gerade aktualisierte Liste sofort an das Back-End, wie im folgenden Konzept gezeigt:
Geben Sie hier die Bildbeschreibung ein

Wenn Sie keine der beiden Lösungen tun, dh wenn Sie dies nur in Ihrem Code sagen:

addToItemArray = () => { 
     this.setState{{ scheduledItemsArray: newObjectListWithMax}}   
     this.postData();
}

<button className="btn btn-secondary btn-block" onClick={this.addToItemArray}>Add Shedule</button>

… Sie werden die Liste veröffentlichen ausschließlich den Punkt “Lieferung an Max”, da der Status bei Ihnen nicht aktualisiert wird this.postData() (wieder, weil es asynchron ist).

Wenn Sie Lösung 1 verwenden, würden Sie einen POST machen, nachdem Sie jedes Zeichen in das Textfeld Schedule Name eingegeben haben!

Es gibt auch andere Möglichkeiten, diesen Anwendungsfall zu berücksichtigen, aber Lösung 2 vermittelt die Absicht am besten, wenn der Code gelesen wird.

Da dieser Anwendungsfall in praktisch jeder Web-App allgegenwärtig ist, ist die in Michaels Antwort erläuterte Callback-Technik ein unverzichtbares Stück Code in jedem Entwickler-Toolkit.

Benutzer-Avatar
Vishal Bisht

Einfach ausgedrückt – this.setState({data: value}) ist von Natur aus asynchron, was bedeutet, dass es sich aus dem Call Stack herausbewegt und nur dann zum Call Stack zurückkehrt, wenn es nicht aufgelöst wird.

Bitte lesen Sie über Event Loop, um ein klares Bild über die asynchrone Natur in JS zu erhalten und warum die Aktualisierung einige Zeit in Anspruch nimmt –

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

Somit –

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

da die Aktualisierung einige Zeit in Anspruch nimmt. Um den obigen Prozess zu erreichen –

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

1015540cookie-checkWarum ändert der Aufruf der Methode „react setState“ den Status nicht sofort?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy