8 ottobre 2026

TanStack Router in React: route type-safe, loader robusti e rotte protette senza “colla” nel codice

Dalla route tree generata automaticamente ai search params tipizzati: un approccio moderno per app complesse, con meno stato locale e più coerenza.

TanStack Router sta diventando una scelta sempre più naturale per applicazioni React articolate: routing dichiarativo, type-safety reale, loader per gestire i dati a livello di rotta, search params tipizzati e protezione delle pagine private. In questo articolo vediamo come ragionare con la route tree, perché il file-based routing cambia il modo di progettare la navigazione e quali vantaggi pratici porta in produzione rispetto a soluzioni più “string-based”.

TanStack Router è uno di quei tool che, una volta capiti i meccanismi, cambiano il modo in cui strutturi un’app React: meno “colla” nei componenti (stato e side-effect sparsi), più logica spostata dove ha senso—nel routing. Il risultato è un’architettura più leggibile, più verificabile e, soprattutto, più type-safe.

In questo articolo mettiamo a fuoco i concetti che fanno davvero la differenza: route tree, root route, file-based routing, loader, search params tipizzati e rotte protette.


Perché serve un router (davvero)

Un router non è solo “cambio pagina senza reload”. È il meccanismo che traduce l’intento dell’utente (un URL) nell’interfaccia corretta.

  • L’utente visita /items/phones → vuole vedere i telefoni.
  • Cambia a /items/cats → vuole vedere i gatti.

Questa corrispondenza URL → UI porta due benefici fondamentali:

  1. Deep linking: ogni punto dell’app può essere raggiunto con un URL condivisibile e bookmarkabile.
  2. Separazione delle responsabilità: la navigazione e la selezione della “pagina” non dipendono da useEffect e variabili locali, ma da regole dichiarative.

Pensalo come un GPS: prende l’URL, lo interpreta, decide dove “portare” l’utente e quale componente renderizzare.


Cosa rende TanStack Router diverso

Molte librerie risolvono il problema del routing (React Router DOM, i router integrati dei framework, ecc.). TanStack Router punta a un obiettivo molto specifico: rendere il routing un’API altamente tipizzata e scalabile.

1) Type-safety “seria” (non cosmetica)

Uno dei problemi più comuni dei router “string-based” è banale ma costoso: scrivi un percorso a mano, sbagli una lettera, e scopri l’errore solo in produzione con un 404.

Con TanStack Router l’idea è opposta: se il progetto è configurato correttamente, molti errori diventano impossibili o vengono segnalati dal type checker/IDE quando stai scrivendo codice.

2) File-based routing

Le rotte derivano da file e cartelle: la struttura del filesystem diventa una rappresentazione concreta dell’albero di navigazione. Questo riduce configurazioni verbosissime e ti obbliga (in senso buono) a mantenere una gerarchia chiara.

3) Loader e dati “router-driven”

La parte più interessante per app complesse: caricare i dati a livello di route invece che dentro i componenti con useEffect.

  • la rotta decide cosa serve
  • il componente si concentra su come mostrarlo

Questo approccio tende a ridurre stato derivato, condizioni sparse, loading duplicati e fetch ripetuti.


Setup: partire col piede giusto

TanStack mette a disposizione una CLI per generare lo scaffolding del progetto router-first.

Concettualmente, il flusso è:

  • crei un progetto con lo scaffolding del router
  • selezioni framework (React)
  • avvii in dev e inizi a costruire le rotte tramite file

Nel progetto troverai anche configurazioni già pronte per plugin utili (es. devtools) e impostazioni pensate per migliorare l’esperienza di sviluppo.


La route tree: il cuore dell’architettura

Quando lavori con file-based routing, l’app non ragiona “direttamente” sui file: serve una struttura intermedia che rappresenti l’albero delle rotte.

Per questo entra in gioco un file generato automaticamente (tipicamente qualcosa come routeTree.gen.ts).

Punti chiave:

  • viene generato: non si modifica a mano
  • contiene la gerarchia completa delle rotte
  • abilita type inference e collegamenti affidabili tra path, parametri e navigazione

Root route e convenzioni

Di solito c’è un file speciale per la root route (es. _root.tsx).

Poi, a livello di cartella routes, le convenzioni più comuni sono:

  • index.tsx → la rotta / (home)
  • about.tsx → la rotta /about
  • login.tsx → la rotta /login

Da lì in poi, cartelle annidate = rotte annidate.

Questo modello diventa potentissimo quando inizi ad avere:

  • layout diversi per sezioni dell’app
  • pagine statiche e aree dinamiche
  • contenuti con URL significativi (SEO e condivisione)

Rotte dinamiche: URL data-driven

In applicazioni reali, spesso una parte dell’URL non è fissa: dipende dai dati.

Esempio classico: una pagina “dettaglio meetup”:

  • /activity/meetup/tapascript
  • /activity/meetup/react-milano

Quella “coda” (tapascript, react-milano, …) non dovrebbe essere hardcoded nei componenti. L’ideale è che:

  • la route dichiari il parametro dinamico
  • un loader usi quel parametro per recuperare i dati
  • il componente renderizzi i dettagli

Quando questo è ben tipizzato, ottieni un vantaggio enorme: i parametri non sono più stringhe indefinite, ma valori previsti dal routing.


Loader: dati prima del rendering, con responsabilità chiare

L’idea dei loader è semplice e molto efficace:

  • la rotta definisce come recuperare i dati necessari
  • la UI riceve dati pronti (e gestisce gli stati di loading/error in modo coerente)

Questo tende a eliminare molti pattern comuni ma fragili:

  • useEffect che dipendono da parametri di URL
  • “loading state” duplicati in più componenti
  • fetch ripetuti perché un componente rimonta

In un’app strutturata bene, il routing diventa il punto naturale dove orchestrare:

  • prefetch
  • caching
  • invalidazioni e refresh

Search params tipizzati: filtri e stato URL-friendly

Una delle tentazioni più frequenti è usare stato locale per i filtri (checkbox, dropdown, query di ricerca). Funziona, ma spesso perdi:

  • condivisione dell’URL con i filtri attivi
  • ripristino dello stato al refresh
  • navigazione browser (back/forward) coerente

Gestire filtri e ricerca attraverso i search params (query string) è spesso la scelta migliore, e TanStack Router spinge verso una gestione più rigorosa e tipizzata.

Risultato pratico:

  • filtri riproducibili e condivisibili
  • meno stato “volatile” nei componenti
  • meno ambiguità su cosa rappresenti lo stato dell’app

Router context vs React context: quando usarli

TanStack Router supporta un concetto di router context per passare informazioni lungo il routing.

È utile quando i dati sono naturalmente legati alla navigazione (ad esempio informazioni di sessione, feature flag legati a sezioni, dipendenze del layer di routing).

Detto questo, non è un rimpiazzo automatico del React context: se stai modellando stato UI generico o logica non legata alle rotte, spesso il contesto React tradizionale resta più appropriato.

La regola pratica: usa router context per ciò che “appartiene” alla navigazione; React context per ciò che appartiene alla UI o al dominio in senso più ampio.


Rotte protette: private area senza hack

Quasi ogni prodotto reale ha aree riservate:

  • dashboard
  • creazione/modifica di contenuti
  • impostazioni utente o admin

Il punto non è solo “bloccare la pagina”, ma farlo in modo coerente e prevedibile:

  • se non sei autenticato e tenti di accedere a una rotta privata → redirect a /login
  • dopo login → ritorno al flusso (o accesso alla rotta richiesta)
  • messaggi e regole non sparsi nei componenti, ma definiti nel routing

Quando la protezione è router-driven, diventa più difficile dimenticarsi un controllo in una pagina secondaria.


Un modello mentale utile: dall’app “component-driven” all’app “route-driven”

Molti progetti React partono così:

  • componenti che leggono parametri
  • useEffect che fetchano dati
  • stato locale che replica l’URL

TanStack Router ti invita a ribaltare l’approccio:

  • la rotta conosce parametri e dipendenze
  • il loader conosce il fetching
  • il componente conosce il rendering

Quando questa separazione regge, l’app è più facile da estendere: aggiungere una nuova sezione o un nuovo layout è spesso una questione di struttura delle rotte, non di incollare logica in giro.


Sintesi e implicazione pratica

TanStack Router non è “solo un altro router”: è un modo più rigoroso di progettare la navigazione in React, particolarmente adatto quando l’app cresce e inizi ad avere bisogno di:

  • rotte annidate con layout coerenti
  • parametri dinamici e pagine data-driven
  • loader affidabili e riutilizzabili
  • filtri via URL (search params) tipizzati
  • protezione delle aree private definita a livello di routing

Se oggi ti capita di vedere useEffect ovunque per inseguire l’URL, o stringhe di path scritte a mano in dieci punti diversi del codice, il passaggio a un routing type-safe e route-driven è uno di quei cambiamenti che ripagano rapidamente—in stabilità, debug e manutenzione.