Menu

L'hook useActionState di React: form, errori e attesa

useActionState racchiude un'azione asincrona, conserva il valore che ha restituito l'ultima volta e ti dice se è ancora in esecuzione. Impara la firma, le form action, la restituzione degli errori di validazione e come chiamarlo fuori da un form.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

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 come action(previousState, ...args). Ciò che restituisce (o in cui si risolve, se è async) diventa il nuovo state.
  • initialState è lo stato prima che l'azione sia mai stata eseguita. Usa la stessa forma che restituisce l'azione, così il componente può leggere state.message anche 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.
  • isPending vale true dal 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.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA