Menu

React useState Hook: Beispiele und typische Fehler

useState gibt einer Komponente einen Wert, der erneutes Rendern übersteht, und einen Setter, der den Bildschirm neu zeichnet, wenn sich der Wert ändert. Lerne die Syntax, Updater-Funktionen, Objekte und Arrays im State und warum ein Wert direkt nach dem Setzen veraltet wirkt.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

useState ist der Hook, mit dem sich eine Komponente zwischen Renders etwas merkt: einen Zähler, den Text in einem Eingabefeld, ob ein Menü offen ist. Jedes Mal, wenn du seinen Setter aufrufst, rendert React die Komponente mit dem neuen Wert erneut.

Klicke auf den Button und ändere dann im Editor useState(0) zu useState(10). Die Vorschau wird neu aufgebaut und der Zähler startet bei 10.

Die Syntax

const [value, setValue] = useState(initialValue);
  • initialValue wird nur beim ersten Render verwendet. Bei jedem späteren Render ignoriert React ihn und gibt den gespeicherten Wert zurück.
  • value ist der aktuelle Wert für diesen Render.
  • setValue ersetzt den Wert und plant einen neuen Render ein.

Die Namen bestimmst du. useState gibt ein Array mit zwei Einträgen zurück und die eckigen Klammern packen es aus, also sind [isOpen, setIsOpen] und [email, setEmail] dasselbe Muster.

Rufe useState auf der obersten Ebene deiner Komponente auf, niemals in einer Schleife, einer Bedingung oder einer verschachtelten Funktion. React ordnet jeden Aufruf anhand der Reihenfolge der Aufrufe seinem gespeicherten Wert zu, deshalb muss diese Reihenfolge bei jedem Render gleich sein (siehe die Regeln der Hooks).

Mehrere State-Werte

Eine Komponente kann useState so oft aufrufen, wie sie es braucht. Jeder Aufruf ist ein eigener, unabhängiger Wert.

State ist eine Momentaufnahme

Der Setter ändert nicht die Variable, die du in der Hand hast. Er sagt React, welchen Wert sie im nächsten Render haben soll. Bis dieser Render passiert, sieht der aktuelle weiterhin den alten Wert.

Öffne die Konsole unter der Vorschau und klicke einmal. Der Handler loggt 0, den alten Wert, und danach loggt die Komponente einen neuen Render mit 1. Hier ist nichts kaputt: count ist für den ganzen Render eine Konstante, und der nächste Render bekommt eine frische.

Updater-Funktionen

Wegen der Momentaufnahme addiert dreimaliges Aufrufen des Setters mit count + 1 nur eins, nicht drei: Jeder Aufruf rechnet 0 + 1. Übergib stattdessen eine Funktion, dann reicht React jedem Aufruf das Ergebnis des vorherigen weiter.

Nutze die Updater-Form immer dann, wenn der nächste Wert vom vorherigen abhängt und das Update nicht direkt aus dem neuesten Render laufen könnte: mehrere Sets in einem Handler, ein setInterval-Callback oder ein Effekt.

Objekte und Arrays im State

React entscheidet, ob erneut gerendert wird, indem es den alten und den neuen Wert mit Object.is vergleicht. Wenn du ein Objekt direkt änderst und dasselbe Objekt zurückgibst, sagt der Vergleich, dass sich nichts geändert hat, und der Bildschirm bleibt, wie er war. Übergib immer ein neues Objekt oder Array.

{ ...user, age: user.age + 1 } kopiert jedes Feld und überschreibt eines. [...tags, 'code'] fügt einen Eintrag hinzu und filter entfernt einen, beide geben ein neues Array zurück. Die Seite zum Aktualisieren von Arrays und Objekten behandelt verschachtelte Objekte, das Bearbeiten eines Eintrags in einer Liste und das Einfügen in der Mitte.

Lazy Initialwert

Das Argument von useState wird bei jedem Render ausgewertet, obwohl React es nur beim ersten Mal nutzt. Wenn die Berechnung teuer ist (localStorage lesen, einen großen String parsen), übergib eine Funktion. React ruft sie einmal auf, beim ersten Render.

// Runs readSavedNotes() on every render, then throws the result away
const [notes, setNotes] = useState(readSavedNotes());

// Runs it once
const [notes, setNotes] = useState(readSavedNotes);
const [notes, setNotes] = useState(() => readSavedNotes());

State mit einem key zurücksetzen

State gehört zur Position einer Komponente im Baum. Wenn du an derselben Stelle einen anderen key renderst, behandelt React sie als neue Komponente und ihr State beginnt von vorn. Das ist der sauberste Weg, ein Formular zurückzusetzen, wenn sich das bearbeitete Objekt ändert.

Tippe eine Nachricht und wechsle dann den Empfänger: Der Entwurf wird geleert. Lösche key={to} und versuche es erneut, dann bleibt der Text, weil React jetzt dasselbe Draft an derselben Stelle sieht.

Typische Fehler

State direkt nach dem Setzen loggen. Du siehst den alten Wert, wie oben gezeigt. Logge im Komponentenkörper oder berechne den nächsten Wert zuerst in eine Variable und nutze diese.

State mutieren. user.age++; setUser(user) übergibt dasselbe Objekt, also wird nichts gerendert. Erst kopieren.

Den Setter während des Renderns aufrufen. <button onClick={setCount(count + 1)}> ruft setCount beim Rendern auf, was erneut rendert, was ihn erneut aufruft. React stoppt diese Schleife mit „Too many re-renders“. Übergib eine Funktion: onClick={() => setCount(count + 1)}.

Werte speichern, die du berechnen kannst. Wenn fullName immer first + ' ' + last ist, berechne es beim Rendern, statt einen dritten State zu halten, der aus dem Takt geraten kann.

Häufig gestellte Fragen

Was gibt useState zurück?

Ein Array mit genau zwei Einträgen: dem aktuellen Wert und einer Funktion, die ihn ersetzt. Die Namen vergibst du selbst per Array-Destrukturierung, nach Konvention [thing, setThing].

Warum aktualisiert sich mein State nicht sofort?

Der Aufruf des Setters ändert die Variable nicht, die du bereits hast. Er bittet React, die Komponente erneut zu rendern, und der neue Wert erscheint in diesem nächsten Render. Im aktuellen Event-Handler ist noch der alte Wert im Scope, deshalb gibt console.log(count) direkt nach setCount(count + 1) die alte Zahl aus.

Wann sollte ich dem Setter eine Funktion übergeben?

Wenn der neue Wert vom alten abhängt und du ihn mehr als einmal setzt oder aus einem Timer oder einem Effekt heraus. setCount(c => c + 1) startet immer vom neuesten Wert, setCount(count + 1) dagegen vom Wert, den dieser Render gesehen hat.

Kann useState ein Objekt oder ein Array speichern?

Ja, aber behandle es als schreibgeschützt. Baue ein neues Objekt oder Array und übergib das an den Setter (setUser({ ...user, name }), setItems([...items, item])). Das bestehende direkt zu ändern löst kein Rendern aus.

Was ist der Unterschied zwischen useState und useReducer?

Beide speichern State. useState passt zu wenigen unabhängigen Werten. useReducer verlagert die Update-Logik in eine Funktion, die eine Action erhält, was besser lesbar ist, wenn viele Events denselben State auf zusammenhängende Weise ändern.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

LOS GEHT'S