Tag: state, frontend, react, redux, context, zustand, architecture
Livello: intermedio
TL;DR: La gestione dello stato definisce il flusso dei dati nell'applicazione. Scegliere il tool giusto dipende dalla frequenza di aggiornamento e dall'ambito dei dati.
Local state: dati isolati all'interno di un singolo componente (es. input di form, toggle).
Global state: dati condivisi tra componenti non direttamente correlati (es. carrello, sessione utente).
Server state: dati asincroni provenienti dal backend, che richiedono gestione di loading, cache ed errori.
URL state: stato memorizzato nei parametri della query string per filtri di ricerca e paginazione.
Il prop drilling avviene quando i dati passano attraverso molti componenti intermedi che non li utilizzano.
La Context API risolve il prop drilling ma può causare re-render dell'intero albero se non ottimizzata.
Librerie esterne come Zustand o Redux mantengono lo store separato dall'albero per aggiornamenti più mirati.
L'immutabilità è fondamentale: lo stato non si modifica mai direttamente, si creano sempre nuove referenze.
Lo stato derivato non va mai salvato a sua volta, ma va calcolato al volo durante il render.
Q: Quando preferisci Context API rispetto a Redux o Zustand?R: Uso Context per dati che cambiano raramente come il tema. Per aggiornamenti frequenti preferisco Zustand per evitare re-render a cascata sui consumer.
Q: Come gestisci i dati in arrivo dalle API? Li metti nello store globale?R: No, evito di mescolare server state e client state. Uso tool dedicati come React Query per gestire cache, invalidazione e stati di caricamento.
Q: Cosa si intende per lifting state up?R: È la pratica di spostare lo stato al genitore comune più vicino, permettendo a più componenti figli di condividerlo e modificarlo tramite prop.
Inserire ogni variabile nello store globale, aumentando la complessità e il rischio di bug.
Mutare lo stato direttamente invece di usare funzioni pure e copie dell'oggetto o array.
Duplicare lo stato derivato sincronizzandolo manualmente invece di ricalcolarlo.
Dimenticare di pulire listener o sottoscrizioni nei componenti che si smontano, causando memory leak.
Passare a Context provider oggetti inline creati a ogni render, forzando l'aggiornamento di tutti i consumer.
// Esempio di store globale minimale con Zustand
import { create } from 'zustand'
interface AuthState {
user: string | null
login: (user: string) => void
logout: () => void
}
export const useAuthStore = create<AuthState>((set) => ({
user: null,
login: (user) => set({ user }),
logout: () => set({ user: null }),
}))