React
Lo stato di un form multi-step
Un form multi-step tiene un solo oggetto di stato e mostra un passo alla volta: se ogni passo ha il suo useState, tornare indietro perde i dati già inseriti.
In sintesi
- Lo stato vive nel contenitore dei passi, non nei singoli passi.
- Il ritorno indietro è gratis se i valori non vengono mai smontati.
- Il pulsante Avanti valida solo i campi del passo visibile.
Un form multi-step tiene un solo oggetto di stato per tutti i passi e ne mostra uno alla volta: se ogni passo ha il suo useState, tornare indietro perde i dati già inseriti.
Uno stato, molti passi
Lo stato del form vive nel componente che contiene i passi, non nei singoli passi. Il passo riceve i valori e una funzione di aggiornamento, e non sa quale sia il passo precedente né quale venga dopo.
const [step, setStep] = useState(0);
const [values, setValues] = useState({ name: "", email: "", plan: "base" });
const update = (field) => (event) =>
setValues((current) => ({ ...current, [field]: event.target.value }));
return step === 0 ? (
setStep(1)} />
) : (
setStep(0)} />
);
Con questa forma il ritorno indietro costa zero: i valori non sono mai stati smontati, quindi il passo precedente li ritrova identici, cursore escluso.
Validare dove si avanza, non dove si digita
- Un errore per passo: il pulsante Avanti controlla solo i campi visibili, così il messaggio riguarda ciò che l'utente sta guardando.
- Nessuna validazione al montaggio: un passo vuoto non mostra errori appena appare, altrimenti sembra già sbagliato.
- Riepilogo derivato: l'ultimo passo legge lo stesso oggetto e non ricostruisce i dati da zero.
Il progetto in quattro comandi
npm create vite@latest multi-step -- --template react
cd multi-step
npm install
npm run dev
Vite, licenza MIT, crea il progetto; i passi si aggiungono come componenti in src/ e lo stato resta in un solo file. Il tempo di render si è misurato nel Profiler di React DevTools, passo per passo.
Record vivi nel catalogo
Tre implementazioni da leggere: multi-step-form, multistep-form e registration-stepper. Per sfogliare per categoria parti da blocchi form.
La limitazione
Lo stato unico costa il render dell'intero form a ogni tasto, perché l'oggetto cambia identità. Su cinquanta campi conviene spezzare lo stato per passo o passare a una libreria con sottoscrizioni per campo, accettando che il riepilogo legga da più fonti.
Dove continuare
Il pattern completo è in form multi-step con shadcn; la gestione dei campi è in react-hook-form con shadcn; il confronto fra stato controllato e non controllato è in form controllati e non.
Domande frequenti
Dove va tenuto lo stato del form?
Nel componente che contiene i passi. Se ogni passo tiene il proprio stato, il valore sparisce quando il passo viene smontato.
Meglio un oggetto solo o un useState per campo?
Un oggetto solo finché i campi sono pochi, perché il riepilogo legge una fonte sola. Oltre una trentina di campi conviene spezzarlo.
Quando si valida un passo?
Quando l'utente prova ad avanzare, non mentre digita e non al montaggio. Così l'errore riguarda un'azione appena fatta.
Come si salva una bozza?
Serializzando l'oggetto di stato in sessionStorage o sul server. Lo stato React da solo sparisce al refresh.
Il passo nascosto resta nel DOM?
Dipende dal rendering condizionale: se smonti il passo, perdi il focus e lo stato locale, ma i valori condivisi restano.