v19.2Latest

Auf Eingaben mit State reagieren

React bietet eine deklarative Möglichkeit, die Benutzeroberfläche zu manipulieren. Anstatt einzelne Teile der Benutzeroberfläche direkt zu manipulieren, beschreibst du die verschiedenen Zustände, in denen sich deine Komponente befinden kann, und wechselst zwischen ihnen als Reaktion auf Benutzereingaben. Dies ähnelt der Denkweise von Designern über die Benutzeroberfläche.

Sie werden lernen
  • Wie sich deklarative UI-Programmierung von imperativer UI-Programmierung unterscheidet
  • Wie du die verschiedenen visuellen Zustände auflistest, in denen sich deine Komponente befinden kann
  • Wie du die Änderungen zwischen den verschiedenen visuellen Zuständen aus dem Code auslöst

Wie sich deklarative UI mit imperativer vergleicht

Wenn du UI-Interaktionen entwirfst, denkst du wahrscheinlich darüber nach, wie sich die Benutzeroberflächeverändertals Reaktion auf Benutzeraktionen. Betrachte ein Formular, das dem Benutzer das Absenden einer Antwort ermöglicht:

  • Wenn du etwas in das Formular eingibst, wird der „Absenden“-Buttonaktiviert.
  • Wenn du auf „Absenden“ drückst, werden sowohl das Formular als auch der Buttondeaktiviert,und ein Ladeindikatorerscheint.
  • Wenn die Netzwerkanfrage erfolgreich ist, wird das Formularausgeblendet,und die „Danke“-Nachrichterscheint.
  • Wenn die Netzwerkanfrage fehlschlägt, erscheint eine Fehlermeldung,und das Formular wirdwieder aktiviert.

Bei derimperativen Programmierungentspricht das oben Gesagte direkt der Art und Weise, wie du Interaktionen implementierst. Du musst die genauen Anweisungen schreiben, um die Benutzeroberfläche je nach dem, was gerade passiert ist, zu manipulieren. Hier ist eine andere Denkweise: Stell dir vor, du sitzt neben jemandem im Auto und sagst ihm Kurve für Kurve, wohin er fahren soll.

In einem Auto, das von einer nervös aussehenden Person, die JavaScript repräsentiert, gefahren wird, befiehlt ein Beifahrer dem Fahrer, eine Abfolge komplizierter Kurve-für-Kurve-Navigationen auszuführen.

Illustriert vonRachel Lee Nabors

Sie wissen nicht, wohin du willst, sie folgen nur deinen Befehlen. (Und wenn du die Wegbeschreibung falsch angibst, landest du am falschen Ort!) Es wirdimperativgenannt, weil du jedes Element, vom Ladeindikator bis zum Button, „befehlen“ musst, indem du dem Computer sagst,wieer die Benutzeroberfläche aktualisieren soll.

In diesem Beispiel für imperative UI-Programmierung wird das FormularohneReact erstellt. Es verwendet nur dasDOMdes Browsers:

Die imperative Manipulation der Benutzeroberfläche funktioniert für isolierte Beispiele gut genug, wird aber in komplexeren Systemen exponentiell schwieriger zu handhaben. Stellen Sie sich vor, Sie müssten eine Seite voller verschiedener Formulare wie dieses aktualisieren. Das Hinzufügen eines neuen UI-Elements oder einer neuen Interaktion würde eine sorgfältige Überprüfung des gesamten bestehenden Codes erfordern, um sicherzustellen, dass Sie keinen Fehler eingeführt haben (z. B. etwas zu vergessen, anzuzeigen oder auszublenden).

React wurde entwickelt, um dieses Problem zu lösen.

In React manipulieren Sie die Benutzeroberfläche nicht direkt – das heißt, Sie aktivieren, deaktivieren, zeigen oder verbergen Komponenten nicht direkt. Stattdessendeklarieren Sie, was Sie anzeigen möchten,und React ermittelt, wie die Benutzeroberfläche aktualisiert werden muss. Stellen Sie sich vor, Sie steigen in ein Taxi und sagen dem Fahrer, wohin Sie möchten, anstatt ihm genau zu sagen, wo er abbiegen soll. Es ist die Aufgabe des Fahrers, Sie dorthin zu bringen, und er kennt vielleicht sogar einige Abkürzungen, an die Sie nicht gedacht haben!

In einem von React gesteuerten Auto bittet ein Passagier darum, an einen bestimmten Ort auf der Karte gebracht zu werden. React findet heraus, wie das geht.

Illustriert vonRachel Lee Nabors

Über die Benutzeroberfläche deklarativ nachdenken

Sie haben oben gesehen, wie man ein Formular imperativ implementiert. Um besser zu verstehen, wie man in React denkt, werden Sie im Folgenden die Neugestaltung dieser Benutzeroberfläche in React durchgehen:

  1. IdentifizierenSie die verschiedenen visuellen Zustände Ihrer Komponente
  2. BestimmenSie, was diese Zustandsänderungen auslöst
  3. RepräsentierenSie den Zustand im Speicher mituseState
  4. EntfernenSie alle nicht wesentlichen Zustandsvariablen
  5. VerbindenSie die Event-Handler, um den Zustand zu setzen

Schritt 1: Identifizieren Sie die verschiedenen visuellen Zustände Ihrer Komponente

In der Informatik hört man vielleicht von einer„Zustandsmaschine“, die sich in einem von mehreren „Zuständen“ befindet. Wenn Sie mit einem Designer zusammenarbeiten, haben Sie vielleicht Mockups für verschiedene „visuelle Zustände“ gesehen. React steht an der Schnittstelle von Design und Informatik, daher sind beide Ideen Quellen der Inspiration.

Zuerst müssen Sie alle verschiedenen „Zustände“ der Benutzeroberfläche visualisieren, die der Benutzer sehen könnte:

  • Leer: Das Formular hat einen deaktivierten „Absenden“-Button.
  • Eingabe: Das Formular hat einen aktivierten „Absenden“-Button.
  • Wird gesendet: Das Formular ist vollständig deaktiviert. Ein Ladekreis wird angezeigt.
  • Erfolg: Statt des Formulars wird eine „Danke“-Nachricht angezeigt.
  • Fehler: Gleich wie der Eingabe-Zustand, aber mit einer zusätzlichen Fehlermeldung.

Genau wie ein Designer möchten Sie die verschiedenen Zustände „mocken“ oder „Mocks“ erstellen, bevor Sie Logik hinzufügen. Hier ist zum Beispiel ein Mock für nur den visuellen Teil des Formulars. Dieser Mock wird durch eine Prop namensstatusmit einem Standardwert von'empty'gesteuert:

Sie können diese Prop beliebig nennen, die Benennung ist nicht wichtig. Versuchen Sie,status = 'empty'instatus = 'success'zu ändern, um die Erfolgsmeldung erscheinen zu lassen. Mocking ermöglicht es Ihnen, schnell an der Benutzeroberfläche zu iterieren, bevor Sie Logik einbinden. Hier ist ein ausgefeilterer Prototyp derselben Komponente, der immer noch durch diestatusProp „gesteuert“ wird:

Schritt 2: Bestimmen, was diese Zustandsänderungen auslöst

Sie können Zustandsaktualisierungen als Reaktion auf zwei Arten von Eingaben auslösen:

  • Menschliche Eingaben,wie das Klicken auf einen Button, das Tippen in ein Feld, das Navigieren über einen Link.
  • Computereingaben,wie das Eintreffen einer Netzwerkantwort, das Abschließen eines Timeouts, das Laden eines Bildes.
Ein Finger.Einsen und Nullen.

Illustriert vonRachel Lee Nabors

In beiden Fällenmüssen SieZustandsvariablensetzen, um die Benutzeroberfläche zu aktualisieren.Für das Formular, das Sie entwickeln, müssen Sie den Zustand als Reaktion auf einige verschiedene Eingaben ändern:

  • Ändern der Texteingabe(durch den Benutzer) sollte den Zustand vonLeer zu Am Tippenwechseln oder zurück, je nachdem, ob das Textfeld leer ist oder nicht.
  • Klicken auf den Senden-Button(durch den Benutzer) sollte den Zustand zuWird gesendetwechseln.
  • Erfolgreiche Netzwerkantwort(vom Computer) sollte den Zustand zuErfolgwechseln.
  • Fehlgeschlagene Netzwerkantwort(vom Computer) sollte den Zustand zuFehlerwechseln, mit der entsprechenden Fehlermeldung.
Hinweis

Beachten Sie, dass Benutzereingaben oftEvent-Handlererfordern!

Um diesen Ablauf zu visualisieren, versuchen Sie, jeden Zustand auf Papier als beschrifteten Kreis und jede Änderung zwischen zwei Zuständen als Pfeil zu zeichnen. Auf diese Weise können Sie viele Abläufe skizzieren und Fehler lange vor der Implementierung ausmerzen.

Flussdiagramm, das sich von links nach rechts bewegt, mit 5 Knoten. Der erste Knoten ist mit 'leer' beschriftet und hat eine Kante mit der Beschriftung 'mit dem Tippen beginnen', die mit einem Knoten namens 'am Tippen' verbunden ist. Dieser Knoten hat eine Kante mit der Beschriftung 'Senden drücken', die mit einem Knoten namens 'wird gesendet' verbunden ist, der zwei Kanten hat. Die linke Kante ist mit 'Netzwerkfehler' beschriftet und verbindet mit einem Knoten namens 'Fehler'. Die rechte Kante ist mit 'Netzwerkerfolg' beschriftet und verbindet mit einem Knoten namens 'Erfolg'.Flussdiagramm, das sich von links nach rechts bewegt, mit 5 Knoten. Der erste Knoten ist mit 'leer' beschriftet und hat eine Kante mit der Beschriftung 'mit dem Tippen beginnen', die mit einem Knoten namens 'am Tippen' verbunden ist. Dieser Knoten hat eine Kante mit der Beschriftung 'Senden drücken', die mit einem Knoten namens 'wird gesendet' verbunden ist, der zwei Kanten hat. Die linke Kante ist mit 'Netzwerkfehler' beschriftet und verbindet mit einem Knoten namens 'Fehler'. Die rechte Kante ist mit 'Netzwerkerfolg' beschriftet und verbindet mit einem Knoten namens 'Erfolg'.

Formularzustände

Schritt 3: Den Zustand im Speicher mituseState

Als nächstes müssen Sie die visuellen Zustände Ihrer Komponente im Speicher mituseStaterepräsentieren. Einfachheit ist entscheidend: Jedes Stück State ist ein „bewegliches Teil“, undSie möchten so wenige „bewegliche Teile“ wie möglich.Mehr Komplexität führt zu mehr Fehlern!

Beginnen Sie mit dem State, derunbedingtvorhanden sein muss. Zum Beispiel müssen Sie dieanswerfür die Eingabe und denerror(falls vorhanden) speichern, um den letzten Fehler zu speichern:

Dann benötigen Sie eine Zustandsvariable, die darstellt, welchen der visuellen Zustände Sie anzeigen möchten. Es gibt normalerweise mehr als eine Möglichkeit, dies im Speicher darzustellen, daher müssen Sie damit experimentieren.

Wenn es Ihnen schwerfällt, sofort die beste Methode zu finden, beginnen Sie damit, genügend Zustände hinzuzufügen, sodass Siedefinitivsicher sind, dass alle möglichen visuellen Zustände abgedeckt sind:

Ihre erste Idee wird wahrscheinlich nicht die beste sein, aber das ist in Ordnung – das Refaktorieren des Zustands ist Teil des Prozesses!

Schritt 4: Entfernen Sie alle nicht wesentlichen Zustandsvariablen

Sie sollten Duplikate im Zustandsinhalt vermeiden, sodass Sie nur das Wesentliche verfolgen. Wenn Sie etwas Zeit in die Refaktorierung Ihrer Zustandsstruktur investieren, werden Ihre Komponenten leichter zu verstehen sein, Duplikate reduziert und unbeabsichtigte Bedeutungen vermieden. Ihr Ziel ist es,Fälle zu verhindern, in denen der Zustand im Speicher keine gültige Benutzeroberfläche darstellt, die ein Benutzer sehen sollte.(Sie möchten beispielsweise niemals eine Fehlermeldung anzeigen und gleichzeitig die Eingabe deaktivieren, da der Benutzer sonst den Fehler nicht korrigieren kann!)

Hier sind einige Fragen, die Sie zu Ihren Zustandsvariablen stellen können:

  • Verursacht dieser Zustand ein Paradoxon?Beispielsweise könnenisTypingundisSubmittingnicht beidetruesein. Ein Paradoxon bedeutet normalerweise, dass der Zustand nicht ausreichend eingeschränkt ist. Es gibt vier mögliche Kombinationen zweier Boolescher Werte, aber nur drei entsprechen gültigen Zuständen. Um den "unmöglichen" Zustand zu entfernen, kannst du diese zu einemstatuskombinieren, der einer von drei Werten sein muss:'typing','submitting'oder'success'.
  • Ist dieselbe Information bereits in einer anderen Zustandsvariablen verfügbar?Ein weiteres Paradoxon:isEmptyundisTypingkönnen nicht gleichzeitigtruesein. Wenn du sie als separate Zustandsvariablen behältst, riskierst du, dass sie nicht synchron sind und Fehler verursachen. Glücklicherweise kannst duisEmptyentfernen und stattdessenanswer.length === 0prüfen.
  • Kannst du dieselbe Information aus dem Gegenteil einer anderen Zustandsvariablen erhalten?isErrorist nicht nötig, weil du stattdessenerror !== nullprüfen kannst.

Nach dieser Bereinigung bleiben 3 (von ursprünglich 7!)essentielleZustandsvariablen übrig:

Du weißt, dass sie essentiell sind, weil du keine davon entfernen kannst, ohne die Funktionalität zu beeinträchtigen.

Deep Dive
„Unmögliche“ Zustände mit einem Reducer eliminieren

Schritt 5: Ereignishandler mit der Zustandsänderung verbinden

Erstelle schließlich Ereignishandler, die den Zustand aktualisieren. Unten siehst du das fertige Formular mit allen verbundenen Ereignishandlern:

Obwohl dieser Code länger ist als das ursprüngliche imperative Beispiel, ist er viel weniger anfällig für Fehler. Indem du alle Interaktionen als Zustandsänderungen ausdrückst, kannst du später neue visuelle Zustände einführen, ohne bestehende zu brechen. Es ermöglicht dir auch zu ändern, was in jedem Zustand angezeigt werden soll, ohne die Logik der Interaktion selbst zu ändern.

Zusammenfassung

  • Deklarative Programmierung bedeutet, die Benutzeroberfläche für jeden visuellen Zustand zu beschreiben, anstatt die Benutzeroberfläche zu micromanagen (imperativ).
  • Bei der Entwicklung einer Komponente:
    1. Identifiziere alle ihre visuellen Zustände.
  • Bestimme die menschlichen und computerbasierten Auslöser für Zustandsänderungen.
  • Modelliere den Zustand mit useState.

Try out some challenges

Challenge 1 of 3:Add and remove a CSS class #

Make it so that clicking on the picture removes the background--active CSS class from the outer <div>, but adds the picture--active class to the <img>. Clicking the background again should restore the original CSS classes.

Visually, you should expect that clicking on the picture removes the purple background and highlights the picture border. Clicking outside the picture highlights the background, but removes the picture border highlight.