TanStack Form: semplificazione dei moduli complessi

TanStack Form

La gestione dei form nel front-end è spesso complessa: in questo ambito, TanStack Form emerge come una soluzione completa, agnostica e performante.

In questo articolo, Massimiliano Attianese, Junior Front-end Developer per Bitrock, condivide la sua esperienza diretta. 

Attraverso test pratici, verranno analizzate le feature più significative di TanStack: dalla tipizzazione con TypeScript all’approccio Headless and Framework Agnostic, fino alla gestione reattiva dello stato.

L’obiettivo è fornire una valutazione il più possibile imparziale, evidenziando i vantaggi e gli aspetti positivi che TanStack Form offre per migliorare la qualità dei form e l’esperienza di sviluppo nelle applicazioni moderne.


Introduzione

La libreria TanStack Form offre agli sviluppatori la possibilità di gestire in toto i form in modo semplice, garantendo sicurezza e performance elevate.

Una delle caratteristiche principali è il supporto nativo a TypeScript. Grazie a una forte tipizzazione, infatti, si ottiene un autocompletamento preciso che riduce al minimo gli errori, garantendo la creazione di form più sicuri e migliorando in modo significativo l’esperienza di sviluppo.

Un’altra feature primaria della libreria è il suo approccio “Headless and Framework Agnostic”, che permette agli sviluppatori di gestire la logica dei moduli in modo completamente indipendente dalla loro interfaccia. Questo consente la creazione di componenti di form altamente personalizzati, riutilizzabili e facilmente integrabili in qualsiasi stack front-end, favorendo modularità e manutenibilità del codice.

Dal punto di vista delle performance, TanStack Form si distingue per il suo approccio reattivo e altamente granulare nella gestione dello stato. Questo significa che, ad ogni cambiamento, vengono aggiornati solo i componenti realmente coinvolti, assicurando così un’ interfaccia rapida e fluida. Tutto ciò avviene senza dover ricorrere a boilerplate o astrazioni complesse, permettendo di ottenere prestazioni ottimizzate con un codice chiaro, leggero e sempre sotto il pieno controllo dello sviluppatore.

Come è possibile leggere dalla documentazione della libreria, questa nasce dalla necessità di avere una soluzione completa per la gestione dei form. Spesso, i framework mettono a disposizione solo funzionalità di base, costringendo gli sviluppatori ad affidarsi a diverse librerie o creare implementazioni personalizzate aumentando il rischio di avere prestazioni insoddisfacenti, codice incoerente nel progetto (o tra i vari progetti) e un aumento dei tempi di sviluppo.

L’utilizzo di TanStack Form garantisce invece una soluzione all-in-one potente, flessibile e facile da usare, con un set completo di strumenti per affrontare le problematiche più comuni legate ai form, tra cui:

  • Binding reattivo dei dati e gestione avanzata dello stato
  • Validazione complessa e gestione centralizzata degli errori
  • Accessibilità e design responsive
  • Compatibilità cross-platform e personalizzazione dello stile


Test della libreria

Ho avuto modo di testare direttamente la libreria realizzando due form dedicati alla creazione di un utente. I due esempi si differenziano sia per struttura (il Basic Form, più semplice ed essenziale, e l’Advanced Form, con un numero maggiore di campi e logiche più complesse), sia per l’approccio utilizzato nella loro implementazione. Grazie a questo tipo di approccio, ho potuto ottenere una visione complessiva delle potenzialità della libreria e maturare un parere personale sull’ esperienza di sviluppo.


Installazione

L’installazione è semplice ed immediata: come per qualsiasi altra libreria, è sufficiente eseguire il comando npm i @tanstack/react-form indicato nella documentazione. Ciò che fa davvero la differenza è proprio la documentazione stessa, che guida lo sviluppatore nella scelta del comando più adatto al proprio ambiente e gestore di pacchetti, rendendo il processo ancora più lineare e privo di dubbi.


Costruzione del Form

Form


Anche nell’utilizzo pratico, TanStack Form  mantiene la promessa di essere semplice ed intuitivo, grazie al suo approccio “Headless and Framework Agnostic”. La documentazione gioca un ruolo fondamentale in quanto permette di selezionare il framework e la versione con cui si sta lavorando, offrendo istruzioni dettagliate ed esempi mirati.

Nel caso del test effettuato, ad esempio, l’applicazione è sviluppata in React e la documentazione propone direttamente l’utilizzo dello specifico hook useForm, che consente di definire la costante form come base di partenza per la costruzione del modulo.

Nell’oggetto che andiamo a creare nell’hook possiamo definire i vari formOptions  tra cui:

  • defaultValues: per definire i valori iniziali del form
  • validators: per definire le regole di validazione applicabili ai vari listeners
  • onSubmit: esecuzione post-submit per form valido
  • onSubmitInvalid: per gestire gli errori quando il form non è valido
  • transform: per mappare/trasformare i dati del form prima del submit
  • listeners: hook per eventi come onChange, onBlur,  onSubmitAsync, ecc..

Il defaultValues  è anche l’origine della forte tipizzazione del form: la libreria riesce infatti, attraverso esso, a inferire l’intera struttura del form, propagando automaticamente le regole ai campi field che creeremo dalla costante form (form.Field).

Durante la compilazione dei form, ho trovato questa feature estremamente comoda, in quanto la compilazione automatica dovuta alla tipizzazione ha velocizzato di molto la stesura del codice in più la segnalazione quasi in real-time di errori dovuti a typo, tipi sbagliati, ecc… ha permesso di evitare errori spesso difficili da individuare.

Stato del Form

TanStack Form mantiene uno stato centralizzato del form, accessibile tramite form.state. Tra i valori più utili troviamo isDirty, isTouched, isSubmitting e isValid che consentono di rispondere in modo coerente a qualsiasi cambiamento. Ad esempio, è possibile disabilitare il pulsante di submit finché il form non è valido, oppure mostrare un indicatore di caricamento durante un submit asincrono. È dunque possibile costruire interfacce reattive senza dover scrivere logica di sincronizzazione manuale.


Diverso Approccio per la costruzione del Form

La libreria risulta agnostica al framework che si sta utilizzando, in quanto centralizza la logica in dei wrapper dei vari campi che creeremo (form.Field); questa caratteristica offre la possibilità di adottare due approcci diversi per la costruzione dei form.

  1. Approccio Standard: 
    Consiste nell’utilizzare direttamente l’API principale di TanStack Form. In questo caso, lo sviluppatore definisce il form creando i campi, gestendo manualmente lo stato interno, le validazioni e il submit. Questo metodo offre molta flessibilità: è possibile personalizzare ogni aspetto del form, ma richiede di scrivere più codice.

    Definizione della costante form con useForm:

Creazione dei campi con form.Field gestendo tutta la logica dell’input in modo specifico e indipendente.

2. Approccio con useAppForm

Un’altra possibilità consiste nell’utilizzo di useAppForm, un wrapper creato per semplificare la costruzione di form standardizzati. Questo approccio preconfigura gran parte della logica comune: di conseguenza, il codice diventa più leggibile e coerente tra form diversi, riducendo il rischio di errori ed accelerando lo sviluppo.

  • Definizione della costante form con useAppForm
  • Definizione struttura e componenti riutilizzabili
  • Esempio di input riutilizzabile:
  • Esempio di costruzione form con l’approccio useAppForm:

Nel mio test ho ricorso a entrambi i metodi: per il form più semplice ho utilizzato l’approccio standard mentre per quello più complesso ho optato per l’approccio con  useAppForm. Ho trovato entrambi gli approcci funzionali e adeguati a specifiche situazioni, soprattutto grazie all’ astrazione della logica nei wrapper forniti dalla libreria che permettono di avere il controllo totale della personalizzazione dei vari input. In particolare, sono rimasto soddisfatto del secondo approccio descritto, in quanto, nonostante il form fosse grande e complesso con presenza di campi complessi e ramificati (come gli array), dopo avere organizzato il codice con la costruzione dei vari input riutilizzabili, il codice del form risultava essere molto chiaro e leggibile.


Validazione

Le regole per la validazione dei vari campi possono essere dichiarate nella proprietà validators della costante form, con la possibilità di usare librerie dedicate come Zod (usato nel test) o Yup, oppure si può definire la regola di validazione nel campo stesso (nella proprietà validators del Form.Field).


Field

All’interno di TanStack Form, ogni input del form viene rappresentato come un field. Utilizzando form.useField(“nome-campo”), otteniamo un oggetto form.Field strettamente tipizzato rispetto al corrispondente valore definito in defaultValues.

Ogni field incapsula tutta la logica necessaria per gestire il proprio stato, per citare alcune delle proprietà a nostra disposizione:

  • value: Valore corrente del campo e aggiornamento automatico quando cambia.
  • error:  Eventuali errori di validazione, derivanti sia dalle regole definite in validators sia dai listener specifici.
  • listeners: Hook personalizzati come onChange, onBlur o onSubmitAsync, che permettono di reagire dinamicamente agli eventi dell’input.
  • mode: Per per definire se il campo in questione rappresenta un singolo valore o una lista di valori (Array). 

Questa struttura permette ai field di essere autonomi ma perfettamente integrati nel form, mantenendo la stessa filosofia di agnosticismo.

In pratica, ogni campo diventa un’unità indipendente e tipizzata, con pieno controllo sulla propria logica, ma al tempo stesso parte integrante del flusso complessivo del form, garantendo sicurezza, coerenza e facilità di manutenzione.

Validazione e gestione degli errori

Ogni field può gestire automaticamente la propria validazione, combinando le regole definite in validators e gli eventuali listener personalizzati. Eventuali errori vengono esposti in field.error e possono essere mostrati direttamente nella UI. In questo modo, è semplice distinguere tra errori locali (singolo campo) e globali (form-wide), garantendo un feedback immediato e consistente all’utente.

Esempio validazione di un campo senza l’utilizzo di schemi di validazione:

ArrayField

Dopo aver visto come Form.Field renda elegante e leggibile la gestione dei singoli campi, la stessa filosofia di semplicità si ritrova negli Array.Field: con TanStack Form è sorprendentemente rapido definire collezioni dinamiche di input, aggiungere o rimuovere elementi e mantenerli sempre sincronizzati con lo stato del form. Per ottenerlo basta specificare una key e il mode=”array”, e ciò che viene restituito è a tutti gli effetti un nuovo Form.Field. Questo significa che si mantengono la stessa API e la stessa coerenza, convalidando e controllando ogni elemento dell’array esattamente come si farebbe con un singolo campo, ma con tutta la flessibilità di un set dinamico.

NestedFields

Così come per gli array, anche la gestione dei nested fields in TanStack Form è sorprendentemente lineare. Definire strutture annidate non richiede pattern complicati né configurazioni particolari: basta dichiarare il path del campo usando la notazione a punti (ad esempio user.address.city) e il form si occupa automaticamente di collegarlo allo stato corretto. L’aspetto positivo è che, anche in questo caso, si lavora sempre con Form.Field, mantenendo la stessa API e le stesse garanzie di validazione e sincronizzazione viste per i campi singoli e per gli array. In questo modo diventa facile modellare form complessi che riflettono fedelmente la struttura dei dati dell’applicazione.

Casi reali e complessi

Grazie alla struttura modulare dei field, TanStack Form supporta facilmente scenari più complessi: form multi-step, campi condizionali che appaiono o cambiano validazione in base ad altri valori, submit asincroni con gestione degli errori dal server. La combinazione di tipizzazione sicura, API coerente e listener flessibili consente di affrontare anche casi avanzati senza perdere leggibilità o controllo.


Conclusione

TanStack Form riesce a combinare tipizzazione sicura, flessibilità e performance in modo sorprendentemente equilibrato. Dal singolo field fino ai form multi-step complessi, ogni elemento è progettato per essere:

  • Autonomo, ma integrato: field, array e nested fields condividono una stessa API intuitiva.
  • Tipizzato e controllato: valori, listener ed errori sono sempre typesafe.
  • Facile da integrare nella UI: componenti controlled, riutilizzabili e coerenti.

Rispetto ad altre librerie, si distingue per il suo approccio headless, le performance ottimizzate e un’API coerente che rende la costruzione di form avanzati più rapida, sicura e leggibile.
La valutazione nel complesso è dunque positiva: l’esperienza d’uso è solida e naturale, e lascia intravedere un potenziale ancora maggiore se sfruttato insieme al resto dell’ecosistema TanStack (come Query, Table o Router). In questo senso, TanStack Form non è solo una libreria di form, bensì un componente che potrebbe diventare sempre più centrale nello sviluppo front-end moderno.


Autore: Massimiliano Attianese, Junior Front-end Developer @ Bitrock


Vuoi saperne di più sui nostri servizi? Compila il modulo e fissa un incontro con il nostro team!