React

Preservare lo stato tra le route

Lo stato sopravvive a un cambio di route solo se il componente resta montato: spostalo sopra il router, oppure mettilo nell’URL, in un context o in storage.

In sintesi

  • Il cambio di route smonta il componente e il suo useState sparisce.
  • Lo stato che sta sopra Routes sopravvive alla navigazione.
  • Filtri e pagina nell’URL sopravvivono a reload e link condivisi.
  • replace evita una voce di cronologia per ogni tasto.

Lo stato sopravvive a un cambio di route solo se il componente che lo possiede resta montato: spostalo sopra il router, oppure mettilo nell’URL, in un context o nello storage, e decidi cosa deve azzerarsi.

Quando React smonta, lo stato muore

Un cambio di route sostituisce l’elemento dentro Routes: il componente della pagina precedente viene smontato e con lui cadono useState, i valori delle ref e le cache locali. Non è un bug, è la stessa regola che azzera un form quando cambi pagina.

Tre posti, tre costi

  • Sopra il router: lo stato vive nell’app e non si perde; costa memoria finché la scheda resta aperta.
  • Nell’URL: filtri e pagina sopravvivono a reload e link condivisi; costa una voce di cronologia per ogni scrittura.
  • In storage: sopravvive alla chiusura del browser; costa una versione dello schema e una scadenza, altrimenti resta per sempre.

Filtri nell’URL

import { useSearchParams } from "react-router";

const [params, setParams] = useSearchParams();

const page = Number(params.get("page") ?? "1");
const query = params.get("q") ?? "";

function setQuery(next) {
  setParams({ q: next, page: "1" }, { replace: true });
}

La pagina e il testo di ricerca arrivano dall’URL, quindi un reload non li perde e un link li porta con sé. replace evita una voce di cronologia per ogni tasto, altrimenti il tasto indietro diventa inutilizzabile.

Lo stato che deve restare fuori

function App() {
  const [draft, setDraft] = useState("");   // survives route changes

  return (
    
      
      ...
    
  );
}

Tutto ciò che sta sopra Routes non viene smontato: la bozza sopravvive alla navigazione. Metti lì solo lo stato che deve davvero durare, perché ogni valore trattenuto è memoria che non si libera.

Il comando

npm create vite@latest router-demo -- --template react-ts
cd router-demo
npm install react-router
npm run dev

React Router è distribuito con licenza MIT; il progetto parte con Vite e la route si dichiara in src/App.tsx. Il pacchetto react-router contiene già i componenti del browser, quindi non serve il vecchio react-router-dom.

Tre record mostrano stato che vive oltre un singolo campo: expandable-tabs tiene la tab aperta, sidebar ricorda se è estesa, e la categoria input raccoglie i campi che quello stato lo producono.

La limitazione

Nessuno dei tre posti è gratis: lo stato sopra il router trattiene memoria, l’URL finisce nella cronologia e nei log del server, lo storage richiede una versione e una scadenza. La scelta sbagliata si vede tardi, quando un utente torna su una pagina e trova i dati di un altro.

Dove continuare

Le tab che vivono nell’URL sono in tab e URL; la navigazione da codice è in navigare con React Router; la stessa idea con i search params di Next.js è in paginazione e search params; il confronto fra i due setup è in Next.js vs Vite.

Domande frequenti

Perché lo stato si perde cambiando route?

Perché il componente della pagina viene smontato e React elimina il suo stato. Solo ciò che resta montato conserva i valori.

Conviene mettere i filtri nell’URL?

Sì quando l’utente deve condividere o ricaricare la vista. Costo: una scrittura di cronologia per aggiornamento, quindi usa replace e un debounce.

Dove metto una bozza di form da conservare?

Sopra il router se serve solo durante la sessione, in sessionStorage se deve sopravvivere a un reload, sul server se deve durare oltre la sessione.

Conservare tutto in un context è una buona idea?

No. Il context trattiene tutto finché l’app resta aperta e ogni aggiornamento rirenderizza chi lo legge: metti solo lo stato davvero condiviso.

Lo stato nell’URL è sicuro?

È pubblico: finisce nella cronologia, nei log e nei link condivisi. Non metterci token, email o dati personali.