State bewahren und zurücksetzen
State ist zwischen Komponenten isoliert. React behält den Überblick darüber, welcher State zu welcher Komponente gehört, basierend auf deren Position im UI-Baum. Sie können steuern, wann der State zwischen erneuten Render-Vorgängen bewahrt oder zurückgesetzt wird.
Sie werden lernen
- Wann React sich entscheidet, den State zu bewahren oder zurückzusetzen
- Wie Sie React zwingen können, den State einer Komponente zurückzusetzen
- Wie Keys und Typen beeinflussen, ob der State bewahrt wird
State ist an eine Position im Render-Baum gebunden
React erstelltRender-Bäumefür die Komponentenstruktur in Ihrer Benutzeroberfläche.
Wenn Sie einer Komponente State geben, denken Sie vielleicht, der State „lebe“ innerhalb der Komponente. Aber der State wird tatsächlich von React gehalten. React ordnet jedes Stück State, das es hält, der richtigen Komponente zu, basierend darauf, wo diese Komponente im Render-Baum sitzt.
Hier gibt es nur ein<Counter />JSX-Tag, aber es wird an zwei verschiedenen Positionen gerendert:
So sehen diese als Baum aus:


React-Baum
Dies sind zwei separate Zähler, weil jeder an seiner eigenen Position im Baum gerendert wird.Sie müssen normalerweise nicht über diese Positionen nachdenken, um React zu verwenden, aber es kann nützlich sein zu verstehen, wie es funktioniert.
In React hat jede Komponente auf dem Bildschirm einen vollständig isolierten State. Wenn Sie beispielsweise zweiCounter-Komponenten nebeneinander rendern, erhält jede ihren eigenen, unabhängigenscore- undhover-State.
Versuchen Sie, beide Zähler zu klicken, und beachten Sie, dass sie sich nicht gegenseitig beeinflussen:
Wie Sie sehen können, wird bei der Aktualisierung eines Zählers nur der State für diese Komponente aktualisiert:


State aktualisieren
React behält den State so lange, wie Sie dieselbe Komponente an derselben Position im Baum rendern. Um dies zu sehen, erhöhen Sie beide Zähler, entfernen Sie dann die zweite Komponente, indem Sie das Kontrollkästchen „Zweiten Zähler rendern“ deaktivieren, und fügen Sie sie dann wieder hinzu, indem Sie es erneut aktivieren:
Beachten Sie, wie der State des zweiten Zählers in dem Moment, in dem Sie ihn nicht mehr rendern, vollständig verschwindet. Das liegt daran, dass React, wenn es eine Komponente entfernt, ihren State zerstört.


Löschen einer Komponente
Wenn Sie „Zweiten Counter rendern“ aktivieren, wird ein zweiterCounterund sein Zustand von Grund auf neu initialisiert (score = 0) und zum DOM hinzugefügt.


Hinzufügen einer Komponente
React bewahrt den Zustand einer Komponente, solange sie an ihrer Position im UI-Baum gerendert wird.Wenn sie entfernt wird oder eine andere Komponente an derselben Position gerendert wird, verwirft React ihren Zustand.
Dieselbe Komponente an derselben Position bewahrt den Zustand
In diesem Beispiel gibt es zwei verschiedene<Counter />-Tags:
Wenn Sie das Kontrollkästchen aktivieren oder deaktivieren, wird der Zählerzustand nicht zurückgesetzt. Egal, obisFancy trueoderfalseist, Sie haben immer einen<Counter />als erstes Kind desdiv, das von der Root-App-Komponente zurückgegeben wird:


Das Aktualisieren desApp-Zustands setzt denCounternicht zurück, weil derCounteran derselben Position bleibt
Es ist dieselbe Komponente an derselben Position, also ist es aus Sicht von React derselbe Zähler.
Fallstrick
Denken Sie daran, dassfür React die Position im UI-Baum – nicht im JSX-Markup – entscheidend ist!Diese Komponente hat zweireturn-Klauseln mit unterschiedlichen<Counter />-JSX-Tags innerhalb und außerhalb derif-Bedingung:
Sie könnten erwarten, dass der Zustand zurückgesetzt wird, wenn Sie das Kontrollkästchen aktivieren, aber das passiert nicht! Das liegt daran, dassbeide dieser<Counter />-Tags an derselben Position gerendert werden.React weiß nicht, wo Sie die Bedingungen in Ihrer Funktion platzieren. Alles, was es „sieht“, ist der Baum, den Sie zurückgeben.
In beiden Fällen gibt dieApp-Komponente ein<div>mit<Counter />als erstem Kind zurück. Für React haben diese beiden Zähler dieselbe „Adresse“: das erste Kind des ersten Kinds der Wurzel. So gleicht React sie zwischen vorherigem und nächstem Render ab, unabhängig davon, wie Sie Ihre Logik strukturieren.
Verschiedene Komponenten an derselben Position setzen den Zustand zurück
In diesem Beispiel ersetzt das Aktivieren des Kontrollkästchens<Counter>durch ein<p>:
Hier wechselst du zwischenverschiedenenKomponententypen an derselben Position. Ursprünglich enthielt das erste Kind des<div>einenCounter. Aber als du einpeingetauscht hast, entfernte React denCounteraus dem UI-Baum und zerstörte seinen Zustand.


Wenn sichCounter in pändert, wird derCountergelöscht und dasphinzugefügt


Beim Zurückschalten wird daspgelöscht und derCounterhinzugefügt
Außerdemsetzt das Rendern einer anderen Komponente an derselben Position den Zustand ihres gesamten Unterbaums zurück.Um zu sehen, wie das funktioniert, erhöhe den Zähler und setze dann das Häkchen:
Der Zählerzustand wird zurückgesetzt, wenn du das Häkchen setzt. Obwohl du einenCounterrenderst, ändert sich das erste Kind desdivvon einemsectionzu einemdiv. Als das Kindsectionaus dem DOM entfernt wurde, wurde der gesamte darunter liegende Baum (einschließlich desCounterund seines Zustands) ebenfalls zerstört.


Wenn sichsection in divändert, wird diesectiongelöscht und das neuedivhinzugefügt


Beim Zurückschalten wird dasdivgelöscht und das neuesectionhinzugefügt.
Als Faustregel gilt:Wenn Sie den Zustand zwischen erneuten Renderings erhalten möchten, muss die Struktur Ihres Baums von einem Rendering zum nächsten „übereinstimmen“.Wenn die Struktur unterschiedlich ist, wird der Zustand zerstört, da React den Zustand zerstört, wenn es eine Komponente aus dem Baum entfernt.
Fallstrick
Deshalb sollten Sie Komponentenfunktionsdefinitionen nicht verschachteln.
Hier ist die KomponentenfunktionMyTextField voninnerhalbMyComponent definiert:
Jedes Mal, wenn Sie auf die Schaltfläche klicken, verschwindet der Eingabezustand! Das liegt daran, dass für jedes Rendering vonandereMyTextField-Funktion erstellt wird. Sie rendern eineMyComponent eine andereKomponente an derselben Position, daher setzt React den gesamten darunterliegenden Zustand zurück. Dies führt zu Fehlern und Leistungsproblemen. Um dieses Problem zu vermeiden,deklarieren Sie Komponentenfunktionen immer auf der obersten Ebene und verschachteln Sie ihre Definitionen nicht.
Zustand an derselben Position zurücksetzen
Standardmäßig bewahrt React den Zustand einer Komponente, solange sie an derselben Position bleibt. Normalerweise ist das genau das, was Sie wollen, daher ist es sinnvoll als Standardverhalten. Manchmal möchten Sie jedoch den Zustand einer Komponente zurücksetzen. Betrachten Sie diese App, die es zwei Spielern ermöglicht, ihre Punktestände während jeder Runde zu verfolgen:
Derzeit bleibt der Punktestand erhalten, wenn Sie den Spieler wechseln. Die beidenCountererscheinen an derselben Position, daher sieht React sie alsdenselbenCounteran, dessenperson-Prop sich geändert hat.
Konzeptionell sollten sie in dieser App jedoch zwei separate Zähler sein. Sie mögen an derselben Stelle in der Benutzeroberfläche erscheinen, aber einer ist ein Zähler für Taylor und der andere ein Zähler für Sarah.
Es gibt zwei Möglichkeiten, den Zustand beim Wechsel zwischen ihnen zurückzusetzen:
- Komponenten an verschiedenen Positionen rendern
- Jeder Komponente miteine explizite Identität geben
key
Option 1: Eine Komponente an verschiedenen Positionen rendern
Wenn Sie möchten, dass diese beidenCounterunabhängig voneinander sind, können Sie sie an zwei verschiedenen Positionen rendern:
- Anfangs ist
isPlayerAtrue. Daher enthält die erste Position denCounter-Zustand und die zweite ist leer. - Wenn Sie auf die Schaltfläche „Nächster Spieler“ klicken, wird die erste Position geleert, aber die zweite enthält nun einen
Counter.


Ausgangszustand


Klicken auf „weiter“


Erneutes Klicken auf „weiter“
Der Zustand jedesCounters wird jedes Mal zerstört, wenn er aus dem DOM entfernt wird. Deshalb setzen sie sich jedes Mal zurück, wenn Sie auf die Schaltfläche klicken.
Diese Lösung ist praktisch, wenn Sie nur wenige unabhängige Komponenten an derselben Stelle rendern. In diesem Beispiel haben Sie nur zwei, daher ist es kein Problem, beide separat im JSX zu rendern.
Option 2: Zustand mit einem Key zurücksetzen
Es gibt auch eine andere, allgemeinere Möglichkeit, den Zustand einer Komponente zurückzusetzen.
Vielleicht haben Siekeys schon bei derRendern von Listengesehen. Keys sind nicht nur für Listen! Sie können Keys verwenden, um React zwischen beliebigen Komponenten unterscheiden zu lassen. Standardmäßig verwendet React die Reihenfolge innerhalb des Elternteils („erster Zähler“, „zweiter Zähler“), um zwischen Komponenten zu unterscheiden. Aber mit Keys können Sie React mitteilen, dass dies nicht nur einersteroder einzweiterZähler ist, sondern ein bestimmter Zähler – zum BeispielTaylorsZähler. Auf diese Weise erkennt ReactTaylorsZähler, wo immer er im Baum erscheint!
In diesem Beispiel teilen sich die beiden<Counter />s keinen Zustand, obwohl sie im JSX an derselben Stelle erscheinen:
Das Wechseln zwischen Taylor und Sarah bewahrt den Zustand nicht. Das liegt daran, dassSie ihnen unterschiedlichekeys gegeben haben:
Die Angabe eineskeys weist React an, denkeyselbst als Teil der Position zu verwenden, anstatt ihrer Reihenfolge innerhalb des Elternteils. Deshalb sieht React sie, obwohl sie im JSX an derselben Stelle gerendert werden, als zwei verschiedene Zähler, und daher teilen sie sich niemals den Zustand. Jedes Mal, wenn ein Zähler auf dem Bildschirm erscheint, wird sein Zustand erstellt. Jedes Mal, wenn er entfernt wird, wird sein Zustand zerstört. Das Umschalten zwischen ihnen setzt ihren Zustand immer wieder zurück.
Hinweis
Denken Sie daran, dass Keys nicht global eindeutig sind. Sie geben nur die Positioninnerhalb des Elternteilsan.
Ein Formular mit einem Key zurücksetzen
Das Zurücksetzen des Zustands mit einem Key ist besonders nützlich bei der Arbeit mit Formularen.
In dieser Chat-App enthält die<Chat>-Komponente den Zustand der Texteingabe:
Versuchen Sie, etwas in das Eingabefeld einzugeben, und drücken Sie dann „Alice“ oder „Bob“, um einen anderen Empfänger auszuwählen. Sie werden feststellen, dass der Eingabezustand erhalten bleibt, weil die<Chat>-Komponente an derselben Position im Baum gerendert wird.
In vielen Apps mag dies das gewünschte Verhalten sein, aber nicht in einer Chat-App!Sie möchten nicht, dass der Benutzer aufgrund eines versehentlichen Klicks eine bereits eingegebene Nachricht an die falsche Person sendet. Um dies zu beheben, fügen Sie einenkeyhinzu:
Dies stellt sicher, dass beim Auswählen eines anderen Empfängers dieChat-Komponente von Grund auf neu erstellt wird, einschließlich jeglichen Zustands im darunterliegenden Baum. React wird auch die DOM-Elemente neu erstellen, anstatt sie wiederzuverwenden.
Das Wechseln des Empfängers löscht nun immer das Textfeld:
Zusammenfassung
- React behält den Zustand, solange dieselbe Komponente an derselben Position gerendert wird.
- Der Zustand wird nicht in JSX-Tags gespeichert. Er ist mit der Baumposition verknüpft, an der Sie diesen JSX platzieren.
- Sie können einen Teilbaum zwingen, seinen Zustand zurückzusetzen, indem Sie ihm einen anderen Schlüssel geben.
- Verschachteln Sie keine Komponentendefinitionen, sonst setzen Sie den Zustand versehentlich zurück.
Try out some challenges
Challenge 1 of 5:Fix disappearing input text #
This example shows a message when you press the button. However, pressing the button also accidentally resets the input. Why does this happen? Fix it so that pressing the button does not reset the input text.
