Menu

React useActionState Hook: Formulare, Fehler, Pending

useActionState umhüllt eine async-Action, behält den Wert, den sie zuletzt zurückgegeben hat, und sagt dir, ob sie noch läuft. Lerne die Signatur, Form Actions, das Zurückgeben von Validierungsfehlern und den Aufruf außerhalb eines Formulars.

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

useActionState ist ein Hook aus React 19, der eine async-Funktion (eine Action) ausführt, ihr Ergebnis als State speichert und dir sagt, ob sie noch läuft. Du rufst ihn als const [state, formAction, isPending] = useActionState(action, initialState) auf und übergibst formAction an ein <form>.

Sende zuerst das leere Formular ab: Die Action gibt ein Fehlerobjekt zurück, und die Meldung erscheint. Tippe dann eine Adresse mit @ und sende erneut ab. Für eine Sekunde zeigt der Button „Subscribing...“ und ist deaktiviert.

Die Syntax

const [state, formAction, isPending] = useActionState(action, initialState, permalink?);
  • action ist die auszuführende Funktion. React ruft sie als action(previousState, ...args) auf. Was sie zurückgibt (oder, wenn sie async ist, womit sie aufgelöst wird), wird zum neuen state.
  • initialState ist der State, bevor die Action je gelaufen ist. Nutze dieselbe Form, die die Action zurückgibt, damit die Komponente state.message auch beim ersten Render lesen kann.
  • state ist das neueste Ergebnis.
  • formAction ist eine umhüllte Version deiner Action. Übergib sie an <form action> oder <button formAction> oder ruf sie selbst auf.
  • isPending ist true vom Start der Action bis zu ihrem Ende.
  • permalink ist optional und nur für Server Functions in einem Framework wichtig: die URL, zu der das Formular gehen soll, wenn es abgesendet wird, bevor JavaScript geladen ist.

Die Action erhält den vorherigen State als erstes Argument. Das ist der häufigste Fehler beim Umstellen eines Formulars: Mit async function save(formData) bekommst du den alten State in formData, und formData.get wirft einen Fehler.

Das Formular mit FormData lesen

Wenn formAction als action eines Formulars genutzt wird, ruft React deine Action mit dem FormData des Formulars auf. Jedes Feld mit einem name ist darin enthalten. Du brauchst kein useState für die Inputs und keinen onChange-Handler, und du rufst kein e.preventDefault() auf: React kümmert sich um das Submit-Event.

Entferne das Häkchen bei Spicy und sende erneut ab: Der Schlüssel spicy verschwindet aus den geloggten Daten, weil eine nicht angehakte Checkbox nichts sendet. Die Action liest außerdem previousState.count, um eins zu addieren, und genau deshalb kommt der vorherige State zuerst.

Validierungsfehler zurückgeben

Die Validierung gehört in die Action. Gib die Fehler als Teil des States zurück und gib die getippten Werte zurück, damit das Formular sie wieder einsetzen kann. Nachdem eine Form Action fertig ist, setzt React die unkontrollierten Felder des Formulars zurück, also käme ein Feld ohne defaultValue={state.values...} nach einem fehlgeschlagenen Absenden leer zurück.

Tippe einen Namen mit einem Buchstaben und ein kurzes Passwort und sende dann ab. Beide Fehler erscheinen, und beide Felder behalten, was du getippt hast. Entferne defaultValue={state.values.name} und sende erneut ab: Das Namensfeld leert sich nach dem Fehler.

Lass in einer echten App den Server das letzte Wort haben. Prüfungen auf dem Client geben schnelles Feedback, aber jeder kann eine Anfrage ohne dein Formular senden.

Die Action außerhalb eines Formulars aufrufen

formAction ist eine Funktion, also kann auch ein Button oder ein Effekt sie aufrufen. Wenn du sie selbst aufrufst, pack den Aufruf in startTransition. Ein Formular erledigt das für dich, ein einfaches onClick nicht, und ohne Transition aktualisiert sich isPending nicht korrekt (React loggt dazu in der Entwicklung einen Fehler).

Klicke ein paar Mal auf Load more. Jeder Aufruf startet vom State, den der vorherige zurückgegeben hat, also werden die Seiten der Reihe nach angehängt. Wenn du die Action erneut aufrufst, während sie noch läuft, stellt React den Aufruf in eine Warteschlange und führt ihn nach dem aktuellen aus, jeweils mit dem neuesten State.

Woher useActionState kommt

Bevor React 19 erschien, war dieser Hook in Canary-Builds als useFormState verfügbar, importiert aus react-dom. Er wurde in useActionState umbenannt, nach react verschoben und bekam den Wert isPending. Wenn du alten Code wie diesen findest, liegt die Lösung im Import und im Namen:

// React canary, before 19
import { useFormState } from 'react-dom';
const [state, formAction] = useFormState(action, initialState);

// React 19
import { useActionState } from 'react';
const [state, formAction, isPending] = useActionState(action, initialState);

Um einen Pending-Zustand in einem tief verschachtelten Submit-Button anzuzeigen, liest useFormStatus aus react-dom den Status des umgebenden Formulars ohne Props. Der Überblick über React 19 führt es mit den anderen Formular-Features auf.

Fehler und wann du etwas anderes nimmst

Wenn die Action einen Fehler wirft, zeigt React die nächste Error Boundary, statt den State zu aktualisieren. Fehler, die man selbst beheben kann, etwa bei der Validierung oder ein vergebener Benutzername, gibst du als State zurück, wie im Registrierungsbeispiel. Echte Fehlschläge lässt du werfen.

useActionState ist für das Ergebnis einer Action. Für einen Wert, der sich sofort aktualisiert, während die Action läuft, etwa einen Like-Zähler, der beim Klick steigen soll, kombiniere ihn mit useOptimistic. Für Eingaben, die sich bei jedem Tastendruck ändern und beim Rendern gelesen werden, sind einfaches useState und ein kontrolliertes Input weiterhin das richtige Werkzeug.

Typische Fehler

Den Parameter für den vorherigen State vergessen. async function save(formData) erhält den vorherigen State in formData. Die Signatur ist bei einem Formular immer (previousState, formData).

Inputs ohne name. FormData enthält nur Felder mit einem Attribut name. Ein Feld mit nur einer id fehlt in formData.get(...), das null zurückgibt.

Überall kontrollierte Inputs. Du kannst in einer Form Action weiterhin value und onChange nutzen, musst aber nicht. Unkontrollierte Felder mit name und defaultValue passen einfacher zu Actions, und das Zurücksetzen nach dem Absenden betrifft nur unkontrollierte Felder.

State in der Action lesen. Der state aus der Komponente ist der Wert aus dem Render, der den Handler erzeugt hat. In der Action nutzt du previousState, das immer das Ergebnis des vorherigen Aufrufs ist, auch wenn mehrere Aufrufe in der Warteschlange standen.

Bei erwarteten Fehlern werfen. Ein geworfener Fehler ersetzt das Formular durch die nächste Error Boundary. Ein falsches Passwort ist kein Absturz; gib es als State zurück.

Häufig gestellte Fragen

Was gibt useActionState zurück?

Ein Array mit drei Einträgen: den aktuellen State (den Wert, den die Action zuletzt zurückgegeben hat, oder den Anfangszustand, bevor sie gelaufen ist), eine neue Action, die du an ein Formular übergibst oder selbst aufrufst, und isPending, das true ist, solange die Action läuft.

Welche Argumente erhält die Action?

Zuerst den vorherigen State, dann das, womit die Action aufgerufen wurde. In einem <form action={formAction}> ist dieses zweite Argument das FormData des Formulars.

Was ist der Unterschied zwischen useActionState und useFormState?

Es ist derselbe Hook. Er erschien in Canary-Versionen von React als useFormState in react-dom, wurde für React 19 in useActionState umbenannt, nach react verschoben und bekam gleichzeitig den Wert isPending.

Kann ich useActionState ohne Formular nutzen?

Ja. Ruf die zurückgegebene Action selbst auf, innerhalb von startTransition, zum Beispiel aus dem onClick eines Buttons. Ohne Transition aktualisiert sich isPending nicht korrekt, und React loggt in der Entwicklung einen Fehler.

Warum wird mein Formular nach dem Absenden geleert?

Nachdem eine Form Action fertig ist, setzt React die unkontrollierten Felder des Formulars zurück, so wie ein Browser nach einem normalen Absenden. Um einen Wert nach einem Fehler zu behalten, gib ihn im State zurück und übergib ihn an den defaultValue des Felds.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

LOS GEHT'S