JavaScript, LocalStorage e SessionStorage per salvare uno stato di ricerca e filtri

by Anastasia P.
SHARE
JavaScript, LocalStorage e SessionStorage per salvare uno stato di ricerca e filtri
© Guida-HTML5.it

Introduzione

Quando costruiamo un’applicazione web, spesso vogliamo che l’utente non perda il contesto del lavoro svolto. Un caso molto comune è la gestione dello stato di ricerca e dei filtri: ad esempio, una pagina con risultati prodotti, una lista di articoli, una dashboard o un catalogo possono avere un campo di ricerca, filtri per categoria, ordinamento e paginazione. Se l’utente ricarica la pagina o torna indietro, è utile ripristinare questi dati senza costringerlo a reinserirli ogni volta.

In questo tutorial vediamo come usare LocalStorage e SessionStorage per salvare in modo semplice lo stato di una ricerca. Il vantaggio è pratico: miglioriamo l’esperienza utente con pochissimo codice, senza bisogno di un backend. Il tema è perfetto per capire quando usare una persistenza lunga, come LocalStorage, e quando invece preferire una memorizzazione temporanea, come SessionStorage.

L’obiettivo sarà salvare e ripristinare:

  • testo cercato;
  • categoria selezionata;
  • ordinamento scelto;
  • stato della pagina corrente.

Vedrai anche come strutturare i dati in modo pulito, come evitare errori con JSON.stringify e JSON.parse, e come scegliere tra i due storage in base al comportamento desiderato.

Codice completo

Qui sotto trovi un esempio completo di una pagina che gestisce una ricerca con filtri e salva lo stato in LocalStorage oppure in SessionStorage a seconda di una modalità configurabile.

// Simuliamo un piccolo catalogo
const products = [
  { id: 1, name: "Mouse wireless", category: "accessori", price: 25 },
  { id: 2, name: "Tastiera meccanica", category: "accessori", price: 90 },
  { id: 3, name: "Monitor 27 pollici", category: "hardware", price: 220 },
  { id: 4, name: "SSD 1TB", category: "hardware", price: 110 },
  { id: 5, name: "Corso JavaScript", category: "formazione", price: 49 },
];

// Chiave unica per salvare lo stato
const STORAGE_KEY = "search-ui-state";

// Cambia qui per usare localStorage o sessionStorage
const storage = localStorage; // oppure sessionStorage

// Elementi UI
const searchInput = document.querySelector("#search");
const categorySelect = document.querySelector("#category");
const sortSelect = document.querySelector("#sort");
const resetButton = document.querySelector("#reset");
const resultsList = document.querySelector("#results");

// Stato iniziale
let state = {
  query: "",
  category: "all",
  sort: "name-asc",
};

// Salva lo stato nello storage scelto
function saveState() {
  storage.setItem(STORAGE_KEY, JSON.stringify(state));
}

// Carica lo stato dallo storage
function loadState() {
  const raw = storage.getItem(STORAGE_KEY);

  if (!raw) return;

  try {
    const parsed = JSON.parse(raw);
    state = { ...state, ...parsed };
  } catch (error) {
    console.warn("Stato non valido, resetto i dati salvati:", error);
    storage.removeItem(STORAGE_KEY);
  }
}

// Filtra e ordina i prodotti
function getFilteredProducts() {
  let filtered = products.filter((product) => {
    const matchesQuery = product.name
      .toLowerCase()
      .includes(state.query.toLowerCase());

    const matchesCategory =
      state.category === "all" || product.category === state.category;

    return matchesQuery && matchesCategory;
  });

  filtered.sort((a, b) => {
    if (state.sort === "price-asc") return a.price - b.price;
    if (state.sort === "price-desc") return b.price - a.price;
    return a.name.localeCompare(b.name);
  });

  return filtered;
}

// Render della lista risultati
function renderResults() {
  const items = getFilteredProducts();

  resultsList.innerHTML = "";

  if (items.length === 0) {
    resultsList.innerHTML = "<li>Nessun risultato trovato</li>";
    return;
  }

  items.forEach((item) => {
    const li = document.createElement("li");
    li.textContent = `${item.name} - ${item.category} - €${item.price}`;
    resultsList.appendChild(li);
  });
}

// Aggiorna la UI con lo stato corrente
function syncUI() {
  searchInput.value = state.query;
  categorySelect.value = state.category;
  sortSelect.value = state.sort;
  renderResults();
}

// Eventi UI
searchInput.addEventListener("input", (event) => {
  state.query = event.target.value;
  saveState();
  renderResults();
});

categorySelect.addEventListener("change", (event) => {
  state.category = event.target.value;
  saveState();
  renderResults();
});

sortSelect.addEventListener("change", (event) => {
  state.sort = event.target.value;
  saveState();
  renderResults();
});

resetButton.addEventListener("click", () => {
  state = {
    query: "",
    category: "all",
    sort: "name-asc",
  };

  storage.removeItem(STORAGE_KEY);
  syncUI();
});

// Inizializzazione
loadState();
syncUI();

Per far funzionare questo script, l’HTML della pagina potrebbe essere molto semplice, ad esempio con un input, due select, un pulsante e una lista risultati. L’importante è che gli id corrispondano a quelli usati nel JavaScript.

Spiegazione

Il codice si basa su un’idea semplice: tenere tutto lo stato in un unico oggetto JavaScript e sincronizzarlo con lo storage del browser ogni volta che cambia.

1. Lo stato dell’interfaccia

Abbiamo definito un oggetto state con tre proprietà:

  • query: il testo inserito nella ricerca;
  • category: la categoria selezionata;
  • sort: il criterio di ordinamento.

Questo approccio è molto utile perché centralizza i dati. Invece di spargere valori in più punti del codice, abbiamo una sola fonte di verità.

2. Salvare i dati nello storage

LocalStorage e SessionStorage salvano solo stringhe. Per questo usiamo JSON.stringify(state) quando scriviamo i dati. In questo modo trasformiamo l’oggetto in una stringa JSON valida.

La funzione saveState() si occupa di aggiornare lo storage ogni volta che l’utente modifica un filtro o la ricerca. È una soluzione semplice e diretta.

3. Ripristinare lo stato

Quando la pagina si carica, la funzione loadState() legge il valore salvato con getItem(). Se il dato esiste, viene convertito di nuovo in oggetto con JSON.parse().

È importante gestire gli errori: se il contenuto nello storage è corrotto o non è un JSON valido, JSON.parse() può fallire. Per questo usiamo un blocco try/catch e, in caso di problema, rimuoviamo il dato errato.

4. Aggiornare la UI

La funzione syncUI() serve a riportare i valori salvati nei controlli della pagina. Dopo aver caricato lo stato, impostiamo:

  • valore dell’input;
  • valore della select categoria;
  • valore della select ordinamento.

Subito dopo richiamiamo renderResults() per mostrare i risultati coerenti con lo stato recuperato.

5. Differenza tra LocalStorage e SessionStorage

La differenza pratica è molto importante:

  • LocalStorage: i dati restano salvati anche dopo la chiusura del browser, finché non vengono rimossi manualmente;
  • SessionStorage: i dati durano solo per la sessione corrente e spariscono quando la scheda viene chiusa.

Per uno stato di ricerca, questa scelta dipende dall’esperienza desiderata. Se vuoi che l’utente ritrovi i filtri anche domani, usa LocalStorage. Se invece vuoi mantenere lo stato solo mentre la scheda è aperta, usa SessionStorage.

Best practice

  • Salva un solo oggetto di stato: è più facile da mantenere rispetto a molte chiavi separate nello storage.
  • Valida sempre i dati letti: non fidarti mai ciecamente del contenuto salvato.
  • Usa try/catch con JSON.parse: evita che un dato corrotto blocchi l’applicazione.
  • Non salvare dati sensibili: password, token di autenticazione o informazioni private non dovrebbero stare in LocalStorage o SessionStorage.
  • Preferisci SessionStorage per stati temporanei: ad esempio filtri di una ricerca breve o preferenze utili solo nella sessione.
  • Limita la frequenza di scrittura: se lo stato cambia molto spesso, valuta un debounce per ridurre le chiamate a storage.
  • Rimuovi i dati inutili: quando lo stato non serve più, usa removeItem() per evitare accumuli non necessari.

Un’altra buona pratica è distinguere chiaramente tra dati applicativi e dati di presentazione. Lo storage del browser è perfetto per piccoli stati UI, ma non è un database. Se i dati diventano complessi o critici, meglio usare un backend o un sistema di persistenza più robusto.

Riepilogo

LocalStorage e SessionStorage sono strumenti semplici ma molto utili per salvare lo stato di una ricerca e dei filtri in un’app web. Con poche righe di JavaScript possiamo:

  • salvare i valori inseriti dall’utente;
  • ripristinarli al caricamento della pagina;
  • migliorare l’esperienza utente;
  • scegliere tra persistenza lunga o temporanea.

La strategia migliore è tenere lo stato in un oggetto unico, serializzarlo con JSON, validarlo al recupero e aggiornare la UI in modo coerente. Questo approccio è pulito, scalabile e facile da adattare a cataloghi, dashboard, liste di contenuti e applicazioni con filtri dinamici.

Approfondisci con risorse ufficiali

  • MDN Web Docs - Window.localStorage: documentazione ufficiale su LocalStorage.
  • MDN Web Docs - Window.sessionStorage: documentazione ufficiale su SessionStorage.
  • MDN Web Docs - JSON.stringify(): per serializzare oggetti in stringhe JSON.
  • MDN Web Docs - JSON.parse(): per convertire JSON in oggetti JavaScript.
  • MDN Web Docs - Web Storage API: panoramica completa sull’API di storage del browser.

SHARE