webentwicklung-frage-antwort-db.com.de

Warum ist setState inreajs Async statt Sync?

Ich habe gerade herausgefunden, dass die Funktion in this.setState() in einer Komponente asynchron ist oder nach Abschluss der Funktion aufgerufen wird, in der sie aufgerufen wurde.

Nun habe ich dieses Blog gesucht und gefunden ( http://www.bennadel.com/blog/2893-setstate-state-mutation-operation-may-be-synchronous-in-reactjs.htm )

Hier stellte er fest, dass setState async ist (wird aufgerufen, wenn der Stapel leer ist) oder sync (aufgerufen, sobald der Aufruf erfolgt ist), je nachdem, wie der Zustandswechsel ausgelöst wurde.

Nun sind diese beiden Dinge schwer zu verdauen 

  1. Im Blog wird die setState-Funktion innerhalb einer Funktion updateState aufgerufen, aber was die updateState-Funktion ausgelöst hat, ist nichts, worüber eine aufgerufene Funktion Bescheid wissen würde.
  2. Warum würden sie setState async machen, da JS eine Sprache mit einem einzelnen Thread ist und dieser setState kein WebAPI- oder Server-Aufruf ist, so dass dies nur für den Thread von JS erforderlich ist. Tun sie dies, damit beim Re-Rendering nicht alle Event-Listener und andere Dinge gestoppt werden oder ein anderes Designproblem vorliegt.
83
Anup

Sie können eine Funktion aufrufen, nachdem der Statuswert aktualisiert wurde:

this.setState({foo: 'bar'}, () => { 
    // Do something here. 
});

Wenn Sie viele Zustände gleichzeitig aktualisieren müssen, gruppieren Sie sie alle in demselben setState:

Instead of:

this.setState({foo: "one"}, () => {
    this.setState({bar: "two"});
});


just do this:

this.setState({
    foo: "one",
    bar: "two"
});
116
JoeTidee

1.) setState-Aktionen sind asynchron und werden zur Leistungssteigerung gebündelt. Dies wird in der Dokumentation von setState erläutert.

setState () mutiert this.state nicht sofort, erstellt jedoch einen ausstehenden Statusübergang. Der Zugriff auf this.state nach dem Aufruf dieser Methode kann möglicherweise den vorhandenen Wert zurückgeben. Es gibt keine Garantie für den synchronen Betrieb von Aufrufen von setState. Aufrufe können zu Leistungssteigerungen im Stapel zusammengefasst werden.


2.) Warum würden sie setState async machen, da JS eine Sprache mit einem einzelnen Thread ist und dieser setState kein WebAPI- oder Server-Aufruf ist:

Dies liegt daran, dass setState den Status ändert und ein erneutes Rendern verursacht. Dies kann eine kostspielige Operation sein, und wenn der Browser synchronisiert wird, reagiert der Browser möglicherweise nicht mehr.
Daher sind die setState-Aufrufe sowohl asynchron als auch für eine bessere Benutzeroberfläche und bessere Leistung im Stapelbetrieb.

63
Sachin

Ich weiß, dass diese Frage alt ist, aber viele Verwirrung für viele Benutzer von reactjs, auch für mich, verursacht hat ..__ Vor kurzem hat Dan Abramov (vom Reagenteam) eine großartige Erklärung darüber verfasst, warum die setState ist asynchron:

https://github.com/facebook/react/issues/11527#issuecomment-360199710

setState soll asynchron sein, und dafür gibt es einige wirklich gute Gründe in der verknüpften Erklärung von Dan Abramov. Dies bedeutet nicht, dass immer asynchron ist - es bedeutet im Wesentlichen, dass Sie abhängig nicht davon abhängen können, synchron ist. ReactJS berücksichtigt viele Variablen in dem Szenario, in dem Sie den Status ändern, um zu entscheiden, wann state tatsächlich aktualisiert und Ihre Komponente erneut gerendert werden soll.
Ein einfaches Beispiel, um dies zu demonstrieren, ist Folgendes: Wenn Sie setState als Reaktion auf eine Benutzeraktion aufrufen, wird state wahrscheinlich sofort aktualisiert (obwohl Sie nicht darauf zählen können), so dass der Benutzer gewonnen hat Sie spüren keine Verzögerung, aber wenn Sie setState als Reaktion auf eine Antwort eines Ajax-Anrufs oder ein anderes Ereignis aufrufen, das nicht vom Benutzer ausgelöst wird, wird der Status möglicherweise mit einer kurzen Verzögerung aktualisiert, da sich der Benutzer nicht wirklich fühlt Diese Verzögerung führt zu einer Verbesserung der Leistung, indem auf das Aktualisieren mehrerer Statusaktualisierungen gewartet wird und das DOM seltener erneut gerendert wird.

11
gillyb

Gute Artikel hier https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setState.md

// assuming this.state.count === 0
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
// this.state.count === 1, not 3

Solution
this.setState((prevState, props) => ({
  count: prevState.count + props.increment
}));

oder Rückruf übergeben this.setState ({.....},callback)

https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b

6
zloctb

Stellen Sie sich vor, Sie erhöhen einen Zähler in einer Komponente:

  class SomeComponent extends Component{

    state = {
      updatedByDiv: '',
      updatedByBtn: '',
      counter: 0
    }

    divCountHandler = () => {
      this.setState({
        updatedByDiv: 'Div',
        counter: this.state.counter + 1
      });
      console.log('divCountHandler executed');
    }

    btnCountHandler = () => {
      this.setState({
        updatedByBtn: 'Button',
        counter: this.state.counter + 1
      });
      console.log('btnCountHandler executed');
    }
    ...
    ...
    render(){
      return (
        ...
        // a parent div
        <div onClick={this.divCountHandler}>
          // a child button
          <button onClick={this.btnCountHandler}>Increment Count</button>
        </div>
        ...
      )
    }
  }

Es gibt einen Count-Handler, der sowohl der übergeordneten als auch der untergeordneten Komponente zugeordnet ist. Dies geschieht absichtlich, so dass wir setState () zweimal innerhalb desselben Kontextes des Click-Event-Bubbling ausführen können, jedoch aus zwei verschiedenen Handlern heraus. 

Wie wir uns vorstellen können, würde ein einzelnes Klickereignis auf die Schaltfläche jetzt beide Handler auslösen, da das Ereignis während der Bubbling-Phase vom Ziel zum äußersten Container sprudelt. 

Deshalb führt btnCountHandler () zuerst den Zählwert auf 1 und dann den DivCountHandler () -Zähler auf 2 aus. 

Die Anzahl erhöht sich jedoch nur auf 1, da Sie in den React Developer-Tools prüfen können.

Das beweist das Reaktion 

  • stellt alle Aufrufe von setState in die Warteschlange

  • kehrt in diese Warteschlange zurück, nachdem die letzte Methode im Kontext ausgeführt wurde (in diesem Fall der divCountHandler)

  • führt alle Objektmutationen, die in mehreren setState-Aufrufen im selben Kontext vorkommen (alle Methodenaufrufe in einer einzelnen Ereignisphase sind z. B. für denselben Kontext), in eine einzige Objektmutationssyntax (Zusammenführen ist sinnvoll, da die Eigenschaften des Status daher unabhängig voneinander aktualisiert werden können) in setState () an erster Stelle)

  • und übergibt es an ein einzelnes setState (), um ein erneutes Rendering aufgrund mehrerer Aufrufe von setState () zu verhindern (dies ist eine sehr grundlegende Beschreibung des Stapelns). 

Resultierender Code, der von RESE ausgeführt wird:

this.setState({
  updatedByDiv: 'Div',
  updatedByBtn: 'Button',
  counter: this.state.counter + 1
})

Um dieses Verhalten zu beenden, werden keine Callbacks übergeben, statt Objekte als Argumente an die setState-Methode zu übergeben.

    divCountHandler = () => {
          this.setState((prevState, props) => {
            return {
              updatedByDiv: 'Div',
              counter: prevState.counter + 1
            };
          });
          console.log('divCountHandler executed');
        }

    btnCountHandler = () => {
          this.setState((prevState, props) => {
            return {
              updatedByBtn: 'Button',
              counter: prevState.counter + 1
            };
          });
      console.log('btnCountHandler executed');
    }

Nachdem die letzte Methode ausgeführt wurde und rea zur Verarbeitung der setState-Warteschlange zurückkehrt, ruft sie einfach den Rückruf für jede setState-Warteschlange auf und übergibt den vorherigen Komponentenstatus.

Auf diese Weise stellt Reacts sicher, dass der letzte Rückruf in der Warteschlange den Status aktualisiert, den alle vorherigen Gegenstücke in die Hand genommen haben.

1
supi

Sie können den folgenden Wrap verwenden, um Sync-Aufruf aufzurufen

this.setState((state =>{
  return{
    something
  }
})

0
Ярослав

Ja, setState () ist asynchron.

Über den Link: https://reactjs.org/docs/react-component.html#setstate

  • React garantiert nicht, dass die Statusänderungen sofort übernommen werden.
  • setState () aktualisiert die Komponente nicht immer sofort.
  • Stellen Sie sich setState () als Anforderung und nicht als sofortigen Befehl zum Aktualisieren der Komponente vor.

Weil sie denken
Über den Link: https://github.com/facebook/react/issues/11527#issuecomment-36019971

... wir sind uns einig, dass das synchrone Rendern von setState () in vielen Fällen ineffizient wäre

Das asynchrone setState () erschwert den Einsteigern das Leben und macht leider sogar Erfahrungen:
- unerwartete Renderprobleme: verzögertes Rendern oder kein Rendern (basierend auf der Programmlogik)
- Übergeben von Parametern ist eine große Sache
unter anderem.

Das folgende Beispiel hat geholfen:

// call doMyTask1 - here we set state
// then after state is updated...
//     call to doMyTask2 to proceed further in program

constructor(props) {
    // ..

    // This binding is necessary to make `this` work in the callback
    this.doMyTask1 = this.doMyTask1.bind(this);
    this.doMyTask2 = this.doMyTask2.bind(this);
}

function doMyTask1(myparam1) {
    // ..

    this.setState(
        {
            mystate1: 'myvalue1',
            mystate2: 'myvalue2'
            // ...
        },    
        () => {
            this.doMyTask2(myparam1); 
        }
    );
}

function doMyTask2(myparam2) {
    // ..
}

Hoffentlich hilft das.