useActionState è un hook di React 19 che esegue una funzione asincrona (un'azione), memorizza come stato ciò che restituisce e ti dice se è ancora in esecuzione. Lo chiami come const [state, formAction, isPending] = useActionState(action, initialState) e passi formAction a un <form>.
Prima invia il form vuoto: l'azione restituisce un oggetto di errore e compare il messaggio. Poi scrivi un indirizzo con una @ e invia di nuovo. Per un secondo il pulsante mostra "Subscribing..." ed è disabilitato.
La sintassi
const [state, formAction, isPending] = useActionState(action, initialState, permalink?);
actionè la funzione da eseguire. React la chiama comeaction(previousState, ...args). Ciò che restituisce (o in cui si risolve, se è async) diventa il nuovostate.initialStateè lo stato prima che l'azione sia mai stata eseguita. Usa la stessa forma che restituisce l'azione, così il componente può leggerestate.messageanche al primo rendering.stateè il risultato più recente.formActionè una versione racchiusa della tua azione. Passala a<form action>o a<button formAction>, oppure chiamala tu.isPendingvaletruedal momento in cui l'azione parte finché non termina.permalinkè facoltativo e conta solo per le Server Function in un framework: l'URL a cui il form dovrebbe andare se viene inviato prima che JavaScript sia caricato.
L'azione riceve lo stato precedente come primo argomento. È l'errore più comune quando si converte un form: scrivere async function save(formData) ti dà il vecchio stato in formData, e formData.get genera un errore.
Leggere il form con FormData
Quando formAction viene usata come action di un form, React chiama la tua azione con i FormData del form. Ogni campo con un name è lì dentro. Non ti servono useState per gli input né un gestore onChange, e non chiami e.preventDefault(): React gestisce l'evento di invio.
Togli la spunta a Spicy e invia di nuovo: la chiave spicy sparisce dai dati registrati, perché una checkbox non spuntata non invia nulla. L'azione legge anche previousState.count per aggiungere uno, ed è per questo che lo stato precedente viene per primo.
Restituire gli errori di validazione
La validazione appartiene all'azione. Restituisci gli errori come parte dello stato, e restituisci i valori digitati dall'utente così il form può rimetterli al loro posto. Dopo che una form action termina, React azzera i campi non controllati del form, quindi un campo senza defaultValue={state.values...} tornerebbe vuoto dopo un invio fallito.
Scrivi un nome di una sola lettera e una password corta, poi invia. Compaiono entrambi gli errori ed entrambi i campi mantengono ciò che hai scritto. Togli defaultValue={state.values.name} e invia di nuovo: il campo del nome si svuota da solo dopo l'errore.
In un'app reale lascia al server l'ultima parola. I controlli sul client danno un riscontro rapido, ma chiunque può inviare una richiesta senza passare dal tuo form.
Chiamare l'azione fuori da un form
formAction è una funzione, quindi anche un pulsante o un effetto possono chiamarla. Quando la chiami tu, racchiudi la chiamata in startTransition. Un form lo fa per te; un semplice onClick no, e senza una transizione isPending non si aggiorna correttamente (in sviluppo React registra un errore al riguardo).
Clicca Load more qualche volta. Ogni chiamata parte dallo stato restituito dalla precedente, quindi le pagine vengono aggiunte in ordine. Se chiami di nuovo l'azione mentre è ancora in esecuzione, React mette in coda la chiamata e la esegue dopo quella attuale, ciascuna con lo stato più recente.
Da dove arriva useActionState
Prima dell'uscita di React 19, questo hook era disponibile nelle build canary come useFormState, importato da react-dom. È stato rinominato useActionState, spostato in react e ha ricevuto il valore isPending. Se trovi codice vecchio come questo, la soluzione sono l'import e il nome:
// 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);
Per mostrare uno stato di attesa in un pulsante di invio annidato in profondità, useFormStatus da react-dom legge lo stato del form genitore senza props. La panoramica di React 19 lo elenca insieme alle altre funzionalità dei form.
Errori e quando usare altro
Se l'azione genera un errore, React mostra l'error boundary più vicino invece di aggiornare lo stato. Per gli errori che l'utente può correggere, come la validazione o un nome utente già preso, restituiscili come stato, come nell'esempio della registrazione. Lascia che siano i veri guasti a generare errori.
useActionState serve per il risultato di un'azione. Per un valore che si aggiorna all'istante mentre l'azione è in esecuzione, come un contatore di mi piace che deve salire al clic, combinalo con useOptimistic. Per un input che cambia a ogni tasto e viene letto durante il rendering, un semplice useState e un input controllato restano lo strumento giusto.
Errori comuni
Dimenticare il parametro dello stato precedente. async function save(formData) riceve lo stato precedente in formData. Per un form la firma è sempre (previousState, formData).
Input senza un name. FormData contiene solo i campi che hanno un attributo name. Un campo con solo un id manca da formData.get(...), che restituisce null.
Input controllati ovunque. Puoi comunque usare value e onChange dentro una form action, ma non sei obbligato. I campi non controllati con name e defaultValue sono l'abbinamento più semplice per le azioni, e l'azzeramento di React dopo l'invio riguarda solo i campi non controllati.
Leggere lo stato dentro l'azione. Lo state del componente è il valore del rendering che ha creato il gestore. Dentro l'azione, usa previousState, che è sempre il risultato della chiamata precedente, anche quando più chiamate sono state messe in coda.
Generare errori per casi previsti. Un errore generato sostituisce il form con l'error boundary più vicino. Una password sbagliata non è un crash; restituiscila come stato.
Domande frequenti
Cosa restituisce useActionState?
Un array di tre elementi: lo stato attuale (il valore restituito l'ultima volta dall'azione, o lo stato iniziale prima che sia mai stata eseguita), una nuova azione da passare a un form o da chiamare tu, e isPending, che vale true mentre l'azione è in esecuzione.
Quali argomenti riceve l'azione?
Prima lo stato precedente, poi ciò con cui l'azione è stata chiamata. In un <form action={formAction}> quel secondo argomento sono i FormData del form.
Qual è la differenza tra useActionState e useFormState?
Sono lo stesso hook. È uscito nelle versioni canary di React come useFormState in react-dom, è stato rinominato useActionState e spostato in react per React 19, e nello stesso momento ha ricevuto il valore isPending.
Posso usare useActionState senza un form?
Sì. Chiama tu l'azione restituita, dentro startTransition, per esempio dall'onClick di un pulsante. Senza una transizione, isPending non si aggiorna correttamente e React registra un errore in sviluppo.
Perché il mio form si svuota dopo l'invio?
Dopo che una form action termina, React azzera i campi non controllati del form, come fa un browser dopo un normale invio. Per mantenere un valore dopo un errore, restituiscilo nello stato e passalo al defaultValue del campo.