# 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.

> Pagina: https://ui.eneawork.it/blog/form-multi-step-stato
> Markdown: https://ui.eneawork.it/blog/form-multi-step-stato.md

*2026-11-01*

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.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats il 1 novembre 2026. La cifra viene da una query all'endpoint, non da una stima: conta i record pubblicati, non la qualità dei componenti.

## 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

## 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.

## FAQ

### 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.
