v19.2Latest

State als Momentaufnahme

State-Variablen mögen wie normale JavaScript-Variablen aussehen, die man lesen und beschreiben kann. State verhält sich jedoch eher wie eine Momentaufnahme. Das Setzen ändert nicht die bereits vorhandene State-Variable, sondern löst ein erneutes Rendern aus.

Sie werden lernen
  • Wie das Setzen von State erneutes Rendern auslöst
  • Wann und wie State-Aktualisierungen erfolgen
  • Warum sich State nicht sofort nach dem Setzen aktualisiert
  • Wie Event-Handler auf eine "Momentaufnahme" des States zugreifen

Das Setzen von State löst Rendering aus

Man könnte sich vorstellen, dass sich Ihre Benutzeroberfläche direkt als Reaktion auf ein Benutzerereignis wie einen Klick ändert. In React funktioniert es etwas anders als dieses mentale Modell. Auf der vorherigen Seite haben Sie gesehen, dassdas Setzen von State ein erneutes Rendering anfordertvon React. Das bedeutet, dass die Oberfläche, um auf das Ereignis zu reagieren, denState aktualisierenmuss.

In diesem Beispiel teiltsetIsSent(true)React mit, die Benutzeroberfläche neu zu rendern, wenn Sie auf "Senden" drücken:

Hier ist, was passiert, wenn Sie auf die Schaltfläche klicken:

  1. DeronSubmit-Event-Handler wird ausgeführt.
  2. setIsSent(true)setztisSentauftrueund reiht ein neues Rendering in die Warteschlange ein.
  3. React rendert die Komponente entsprechend dem neuenisSent-Wert neu.

Werfen wir einen genaueren Blick auf die Beziehung zwischen State und Rendering.

Rendering erstellt eine Momentaufnahme

"Rendering"bedeutet, dass React Ihre Komponente aufruft, die eine Funktion ist. Der JSX, den Sie aus dieser Funktion zurückgeben, ist wie eine Momentaufnahme der Benutzeroberfläche zu einem bestimmten Zeitpunkt. Ihre Props, Event-Handler und lokalen Variablen wurden alleanhand des States zum Zeitpunkt des Renderings berechnet.

Im Gegensatz zu einem Foto oder einem Filmausschnitt ist die UI-„Momentaufnahme“, die Sie zurückgeben, interaktiv. Sie enthält Logik wie Event-Handler, die festlegen, was als Reaktion auf Eingaben passiert. React aktualisiert den Bildschirm, um dieser Momentaufnahme zu entsprechen, und verbindet die Event-Handler. Dadurch löst das Drücken einer Schaltfläche den Klick-Handler aus Ihrem JSX aus.

Wenn React eine Komponente neu rendert:

  1. React ruft Ihre Funktion erneut auf.
  2. Ihre Funktion gibt eine neue JSX-Momentaufnahme zurück.
  3. React aktualisiert dann den Bildschirm, um der von Ihrer Funktion zurückgegebenen Momentaufnahme zu entsprechen.
  1. React führt die Funktion aus
  2. Berechnung der Momentaufnahme
  3. Aktualisierung des DOM-Baums

Illustriert vonRachel Lee Nabors

Als Gedächtnis einer Komponente ist der State nicht wie eine normale Variable, die nach dem Rückgabewert Ihrer Funktion verschwindet. Der State „lebt“ tatsächlich in React selbst – wie auf einem Regal! – außerhalb Ihrer Funktion. Wenn React Ihre Komponente aufruft, gibt es Ihnen eine Momentaufnahme des States für dieses spezifische Rendering. Ihre Komponente gibt eine Momentaufnahme der UI mit einem frischen Satz von Props und Event-Handlern in ihrem JSX zurück, alles berechnetunter Verwendung der State-Werte aus diesem Rendering!

  1. Sie weisen React an, den State zu aktualisieren
  2. React aktualisiert den State-Wert
  3. React übergibt eine Momentaufnahme des State-Werts an die Komponente

Illustriert vonRachel Lee Nabors

Hier ist ein kleines Experiment, um zu zeigen, wie das funktioniert. In diesem Beispiel könnten Sie erwarten, dass das Klicken auf die Schaltfläche „+3“ den Zähler dreimal erhöht, weil essetNumber(number + 1)dreimal aufruft.

Sehen Sie, was passiert, wenn Sie auf die Schaltfläche „+3“ klicken:

Beachten Sie, dassnumbernur einmal pro Klick erhöht wird!

Das Setzen des Zustands ändert ihn nur für dasnächsteRendering.Während des ersten Renderings warnumber 0. Deshalb ist indessenonClick-Handler der Wert vonnumberimmer noch0, selbst nachdemsetNumber(number + 1)aufgerufen wurde:

Hier ist, was der Klick-Handler dieses Buttons React anweist zu tun:

  1. setNumber(number + 1):numberist0, alsosetNumber(0 + 1).
    • React bereitet vor,numberbeim nächsten Rendern auf1zu ändern.
  2. setNumber(number + 1):numberist0, alsosetNumber(0 + 1).
    • React bereitet vor,numberbeim nächsten Rendern auf1zu ändern.
  3. setNumber(number + 1):numberist0, alsosetNumber(0 + 1).
    • React bereitet vor,numberbeim nächsten Rendern auf1zu ändern.

Obwohl SiesetNumber(number + 1)dreimal aufgerufen haben, istdieses Render-Vorgangsimmernumberim Event-Handler0, also setzen Sie den State dreimal auf1. Deshalb rendert React die Komponente, nachdem der Event-Handler abgeschlossen ist, mitnumbergleich1neu und nicht mit3.

Sie können sich das auch vorstellen, indem Sie State-Variablen gedanklich durch ihre Werte im Code ersetzen. Da die State-Variablenumber für 0ist, sieht der Event-Handler so aus:diesen Render-Vorgang

Für das nächste Rendering istnumber 1, also sieht der Klick-Handlerdieses Renderings so aus:

Deshalb wird ein erneuter Klick auf die Schaltfläche den Zähler auf2setzen, dann beim nächsten Klick auf3und so weiter.

State im Zeitverlauf

Nun, das war unterhaltsam. Versuchen Sie zu erraten, was ein Klick auf diese Schaltfläche anzeigen wird:

Wenn Sie die Substitutionsmethode von vorhin verwenden, können Sie erraten, dass die Warnung "0" anzeigt:

Aber was wäre, wenn Sie einen Timer für die Warnung setzen, sodass sie erstnachdem erneuten Rendern der Komponente ausgelöst wird? Würde sie "0" oder "5" anzeigen? Machen Sie eine Vermutung!

Überrascht? Wenn Sie die Substitutionsmethode verwenden, können Sie den "Schnappschuss" des Zustands sehen, der an die Warnung übergeben wurde.

Der in React gespeicherte Zustand hat sich möglicherweise geändert, wenn die Warnung ausgeführt wird, aber sie wurde mit einem Schnappschuss des Zustands zum Zeitpunkt der Benutzerinteraktion geplant!

Der Wert einer Zustandsvariable ändert sich während eines Renders nie,selbst wenn der Code ihres Event-Handlers asynchron ist. Innerhalbdieses RendersonClickbleibt der Wert vonnumberweiterhin0, auch nachdemsetNumber(number + 5)aufgerufen wurde. Sein Wert wurde "festgelegt", als React durch den Aufruf Ihrer Komponente einen "Schnappschuss" der UI erstellt hat.

Hier ist ein Beispiel dafür, wie dies Ihre Event-Handler weniger anfällig für Timing-Fehler macht. Unten sehen Sie ein Formular, das eine Nachricht mit einer Verzögerung von fünf Sekunden sendet. Stellen Sie sich dieses Szenario vor:

  1. Sie drücken die Schaltfläche "Senden", um "Hallo" an Alice zu senden.
  2. Bevor die fünfssekündige Verzögerung endet, ändern Sie den Wert des Felds "An" zu "Bob".

Was erwarten Sie, dass diealertanzeigt? Würde sie "Sie sagten Hallo zu Alice" anzeigen? Oder würde sie "Sie sagten Hallo zu Bob" anzeigen? Machen Sie eine Vermutung basierend auf Ihrem Wissen, und probieren Sie es dann aus:

React hält die Zustandswerte innerhalb der Event-Handler eines Renders „fest“.Sie müssen sich keine Sorgen machen, ob sich der Zustand geändert hat, während der Code läuft.

Aber was, wenn Sie den neuesten Zustand vor einem erneuten Rendern lesen möchten? Dann sollten Sie eineZustandsaktualisierungsfunktionverwenden, die auf der nächsten Seite behandelt wird!

Zusammenfassung

  • Das Setzen eines Zustands fordert ein neues Rendering an.
  • React speichert den Zustand außerhalb Ihrer Komponente, als ob er auf einem Regal stünde.
  • Wenn SieuseStateaufrufen, gibt React Ihnen eine Momentaufnahme des Zustandsfür dieses Rendering.
  • Variablen und Event-Handler „überleben“ keine erneuten Renderings. Jedes Rendering hat seine eigenen Event-Handler.
  • Jedes Rendering (und die darin enthaltenen Funktionen) wird immer die Momentaufnahme des Zustands „sehen“, die ReactdiesemRendering gegeben hat.
  • Sie können sich den Zustand in Event-Handlern gedanklich ersetzen, ähnlich wie Sie über das gerenderte JSX denken.
  • Event-Handler, die in der Vergangenheit erstellt wurden, haben die Zustandswerte aus dem Rendering, in dem sie erstellt wurden.

Probieren Sie einige Herausforderungen aus

Challenge 1 of 1:Implementieren Sie eine Ampel #

Hier ist eine Fußgängerampel-Komponente, die umschaltet, wenn der Knopf gedrückt wird:

Fügen Sie einen alert zum Klick-Handler hinzu. Wenn die Ampel grün ist und „Gehen“ anzeigt, sollte ein Klick auf den Knopf „Als Nächstes: Stopp“ sagen. Wenn die Ampel rot ist und „Stopp“ anzeigt, sollte ein Klick auf den Knopf „Als Nächstes: Gehen“ sagen.

Macht es einen Unterschied, ob Sie den alert vor oder nach dem setWalk-Aufruf platzieren?