Benutzen der State Hook
Hooks sind ein neues Feature in React 16.8. Damit lassen sich State und andere React Features nutzen, ohne dass eine Klasse geschrieben werden muss.
Die Einführungsseite verwendete dieses Beispiel um dir einen Ersteinblick in die Hooks zu bieten:
import React, { useState } from 'react';
function Example() {
// Deklariere eine neue State Variable, die wir "count" nennen werden const [count, setCount] = useState(0);
return (
<div>
<p>Du hast mich {count} mal geklickt</p>
<button onClick={() => setCount(count + 1)}>
Klick mich
</button>
</div>
);
}
Wir beginnen mit dem Lernprozess über Hooks, indem wir diesen Code mit einem entsprechenden Klassenbeispiel vergleichen.
Gleichwertiges Klassenbeispiel
Falls du bereits mit den React-Klassen vertraut bist, dann sollte dir der nachfolgende Code bekannt vorkommen:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>du hast mich {this.state.count} mal geklickt</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Klick mich
</button>
</div>
);
}
}
Der State startet mit { count: 0 }
und wir erhöhen state.count
, wenn der Benutzer auf einen Button klickt, indem this.setState()
aufgerufen wird. Nachfolgend werden wir auf der gesamten Seite Ausschnitte aus dieser Klasse verwenden.
Hinweis
Du fragst dich vielleicht, warum wir hier einen Zähler anstelle eines realistischeren Beispiels verwenden. Damit wollen wir uns vorerst auf die API konzentrieren, während wir noch unsere ersten Schritte mit Hooks machen.
Hooks und Funktionskomponenten
Zur Erinnerung: In React sehen die Funktionskomponenten so aus:
const Example = (props) => {
// Du kannst hier Hooks verwenden!
return <div />;
}
oder so:
function Example(props) {
// Du kannst hier Hooks verwenden!
return <div />;
}
Wahrscheinlich weißt du bereits, dass sich diese Komponenten “Zustandslose Komponenten” nennen. Nun führen wir die Möglichkeit ein, Zustände in den Komponenten zu verwenden, dementsprechend bevorzugen wir die Bezeichnung “Funktionskomponenten”.
Hooks funktionieren nicht innerhalb von Klassen. Aber du kannst sie anstelle von Klassen verwenden.
Was ist ein Hook?
Wir fangen mit dem Import des useState
Hooks aus React an:
import React, { useState } from 'react';
function Example() {
// ...
}
Was ist ein Hook? Ein Hook ist eine spezielle Funktion, mit der du dich in React-Funktionalitäten “einhaken” kannst. Schauen wir uns beispielsweise die useState
-Funktion an, sie ist ein Hook, mit dem wir States zu einer zustandslosen Komponente hinzufügen können, so dass wir die sogenannte Funktionskomponente erhalten. Wir werden später weitere Hooks kennenlernen.
Wann sollte ich einen Hook verwenden? Falls du bereits eine zustandslose Komponente verwendest und später feststellst, dass du die Komponente um States erweitern musst, dann musstest du früher deine Komponente in eine Klassenkomponente umschreiben, dies ist nicht mehr nötig, da du jetzt Hooks verwenden kannst. Dies werden wir jetzt sofort tun!
Hinweis:
Es gibt einige spezielle Regeln dafür, wo man innerhalb einer Komponente Hooks verwenden kann und wo nicht. Wir werden sie in Regeln von Hooks lernen.
Deklarierung einer State-Variable
In einer Klasse initialisieren wir den count
-State mit 0
, in dem wir this.state
auf { count: 0 }
im Konstruktor setzen:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 }; }
In einer Funktionskomponente existiert das Schlüsselwort this
nicht, wodurch wir this.state
weder zuweisen noch lesen können. Stattdessen rufen wir die useState
-Hook direkt in unserer Komponente auf:
import React, { useState } from 'react';
function Example() {
// Deklariere eine neue State-Variable, die wir "count" nennen werden const [count, setCount] = useState(0);
Was bewirkt das Aufrufen der useState
-Funktion? Es deklariert eine “State-Variable”. Die Variable heißt count
, aber wir könnten sie beliebig nennen, wie z.B. banane
. Dies ist eine Möglichkeit, einige Werte zwischen den Funktionsaufrufen zu “erhalten” — useState
ist eine neue Möglichkeit wie man exakt die selben Eigenschaften zu benutezn, wie bei this.state
in einer Klasse. In der Regel “verschwinden” Variablen, wenn eine Funktion fertig ausgeführt ist, jedoch bleiben die State-Variablen durch React erhalten.
Welche Argumente können wir an die useState
-Funktion übergeben? Das einzige Argument, dass der useState()
Hook verwendet ist der initiale Zustand. Anders als es bei Klassen der Fall ist, muss der State nicht unbedingt ein Objekt sein. Wir könnten z.B. eine Zahl oder eine Zeichenkette verwenden falls dies für uns ausreichend ist. In unserem Beispiel ist die Verwendung einer Zahl ausreichend, da wir lediglich die Anzahl der Klicks auswerten möchten, demzufolge übergeben wir 0
als initialen Wert unserer State-Variable. (Falls wir zwei verschiedene Werte im State speichern wollen, rufen wir useState()
zweimal auf.)
Was gibt die useState
-Funktion zurück? Sie gibt ein Tupel zurück: der aktuelle State und eine Funktion die, den aktuellen State aktualisieren kann. Aus diesem Grund schreiben wir const [count, setCount] = useState()
. Dies ist vergleichbar mit this.state.count
und this.setState
die in Klassen verwendet werden, mit dem einzigen Unterschied, dass man sie als Tupel erhält. Falls du mit der von uns verwendeten Syntax nicht vertraut bist, werden wir am Ende dieser Seite nochmal darauf zurückkommen.
Da wir nun wissen, was der useState
Hook macht, sollte unser Beispiel mehr Sinn machen:
import React, { useState } from 'react';
function Example() {
// Deklariere eine neue State-Variable, die wir "count" nennen werden const [count, setCount] = useState(0);
Wir deklarieren eine State-Variable namens count
und setzen sie auf 0
. React merkt sich den aktuellen Wert der Variable zwischen dem neu Rendern und stellt uns diesen für unsere Funktion zur Verfügung. Falls wir den Wert der State-Variable count
aktualisieren möchten, können wir die Methode setCount
aufrufen.
Hinweis
Du fragst dich vielleicht: Warum heißt die Hook
useState
anstattcreateState
?“Create” wäre nicht ganz zutreffend, da der State nur beim ersten Rendern der Komponente erstellt wird. Während der nachfolgenden Rendervorgänge stellt uns die
useState
-Funktion den aktuellen State bereit. Andernfalls wäre es überhaupt kein “state”! Es hat auch seinen Grund, weshalb die Namen der Hooks immer mituse
beginnen. Die Gründe dafür werden wir später in den Regeln von Hooks erfahren.
Lesen des States
Wenn wir den aktuellen Zählerstand in einer Klasse anzeigen lassen wollen, lesen wir this.state.count
:
<p>Du hast mich {this.state.count} mal geklickt</p>
In einer Funktion können wir count
direkt verwenden:
<p>Du hast mich {count} mal geklickt</p>
Aktualisieren des States
In einer Klasse müssen wir this.setState()
aufrufen, um den count
-State zu aktualisieren:
<button onClick={() => this.setState({ count: this.state.count + 1 })}> Klick mich
</button>
In einer Funktion haben wir bereits setCount
und count
als Variablen, so dass wir this
nicht mehr benötigen:
<button onClick={() => setCount(count + 1)}> Klick mich
</button>
Zusammenfassung
Wir möchten nun das Gelernte Zeile für Zeile zusammenfassen um unseren Wissensstand zu prüfen.
1: import React, { useState } from 'react'; 2:
3: function Example() {
4: const [count, setCount] = useState(0); 5:
6: return (
7: <div>
8: <p>Du hast mich {count} mal geklickt</p>
9: <button onClick={() => setCount(count + 1)}>10: Klick mich
11: </button>
12: </div>
13: );
14: }
- Zeile 1: Wir importieren die
useState
-Hook aus React, dadurch können wir einen lokalen State in einer Funktionskomponente halten. - Zeile 4: Innerhalb der
Example
-Komponente deklarieren wir durch einen Aufruf desuseState
-Hooks eine neue State-Variable, die ein Tupel zurückgibt, dessen Inhalte wir dann Namen zuweisen. Wir nennen unsere Variablecount
, da sie die Anzahl der Button-Klicks enthält. Wir initialisieren Null, indem wir0
als einziges Argument anuseState
geben. Die zweite Variable die zurückgegeben wird ist eine Funktion. Sie erlaubt uns den Wert voncount
zu aktualisieren, dementsprechend nennen wir siesetCount
. - Zeile 9: Beim Klick durch einen User auf den Button rufen wir
setCount
mit einem neuen Wert auf. React wird dann dieExample
-Komponente erneut rendern und ihr den neuen Wert für dencount
-State übergeben.
Auf den ersten Blick mag dies eine Menge sein. Überstürzte nichts! Wenn du dich in der Fülle der Informationen verlierst, dann schau dir am Besten den oben bereitgestellten Code nochmal genauer an und wiederhole die dargestellten Schritte von oben nach unten. Wir versprechen dir, dass wenn du versuchst zu “vergessen” wie der State in Klassen funktioniert und du den Code mit kühlem Kopf anschaust, es Sinn machen wird.
Tipp: Welche Bedeutung haben die eckigen Klammern?
Möglicherweise sind dir die eckigen Klammern aufgefallen, die wir bei der Deklaration der State-Variablen verwendet haben:
const [count, setCount] = useState(0);
Die Namen auf der linken Seite sind kein Bestandteil der React-API. Du kannst deine eigenen State-Variablen frei benennen:
const [fruit, setFruit] = useState('banane');
Diese JavaScript-Syntax wird als “Destrukturierende Array-Zuweisung” bezeichnet. Dies bedeutet, dass wir zwei neue Variablen fruit
und setFruit
erstellen, wobei fruit
auf den ersten Wert gesetzt wird, der von der useState
-Hook zurückgegeben wird und setFruit
auf den zweiten. Dies ist gleichwertig mit dem folgenden Code:
var fruitStateVariable = useState('banane'); // Gibt ein Tupel zurück
var fruit = fruitStateVariable[0]; // Erstes Element im Tupel
var setFruit = fruitStateVariable[1]; // Zweites Element im Tupel
Bei der Deklaration einer State-Variable mit Hilfe von useState
erhalten wir einen Tupel zurück — ein Array mit zwei Werten. Der erste Wert ist der aktuelle des States, der zweite eine Funktion, mit der wir den Wert des States aktualisieren können. Die Verwendung von [0]
und [1]
um auf den Inhalt der Hook zuzugreifen mag etwas verwirrend sein, dementsprechend verwenden wir die Array-Destrukturierung.
Hinweis
Möglicherweise fragst du dich, woher React nun weiß, welche Komponente es
useState
zuordnen muss, da wir so etwas wiethis
nicht an React weitergeben. Wir werden die Antwort auf diese Frage, sowie zahlreiche andere Fragen in der FAQ-Sektion beantworten.
Tipp: Verwenden mehrerer State-Variablen
Die Deklaration von State-Variablen als ein Tupel in der Form [something, setSomething]
ist insofern praktisch, da es uns erlaubt den State-Variablen unterschiedliche Namen zu geben, dies ist nützlich wenn man mehrere States verwenden möchte:
function ExampleWithManyStates() {
// Deklaration von mehreren State-Variablen!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banane');
const [todos, setTodos] = useState([{ text: 'Hooks erlernen' }]);
In der obigen Komponente stehen uns age
, fruit
, und todos
als lokale Variablen zur Verfügung, die wir ebenfalls individuell aktualisieren können:
function handleOrangeClick() {
// Vergleichbar mit this.setState({ fruit: 'orange' })
setFruit('orange');
}
Du brauchst nicht zahlreichen State-Variablen zu verwenden. Die Variablen können problemlos Arrays oder Objekte halten, dementsprechend kannst du zusammenhängende Daten gruppieren. Beachte aber, dass im Gegensatz zu der in Klassen verwendeten Funktion this.setState
die Aktualisierung durch die Hooks etwas anders funktioniert, da die State-Variable ersetzt wird, anstatt sie mit dem bereits vorhandenen State zu verschmelzen.
Wir geben weitere Empfehlungen zur Aufteilung unabhängiger State-Variablen die du in den FAQ nachlesen kannst.
Nächste Schritte
Auf dieser Seite haben wir uns über einen der von React zur Verfügung gestellten Hooks, den sogenannten useState
-Hook. Wir werden es gelegentlich auch als “State Hook” bezeichnen. Es ermöglicht uns einen lokalen State zu einer React-Funktionskomponente hinzuzufügen — welches wir zum ersten Mal überhaupt getan haben!
Wir haben ebenfalls ein wenig mehr darüber erfahren, was Hooks überhaupt sind. Hooks sind Funktionen, mit denen man sich über Funktionskomponenten in die React-Funktionalität “einhaken” kann. Ihr Name beginnt immer mit use
. Es gibt zahlreiche weitere Hooks, die wir noch nicht kennengelernt haben.
Fahren wir nun fort mit der nächsten Hook: useEffect
. Diese ermöglicht dir die Durchführung von Seiten-Effekten innerhalb von Komponenten und ähnelt den Lifecycle-Methoden in Klassen.