Tag: state, react, redux, context, frontend, zustand
Livello: intermedio
TL;DR: Pattern e strumenti per gestire in modo prevedibile i dati condivisi tra componenti, evitando il prop drilling e ottimizzando le performance di rendering.
Lo stato locale (Local State) appartiene a un singolo componente, gestito tipicamente con useState o useReducer.
Lo stato globale (Global State) è condiviso e accessibile da molteplici componenti ovunque nell'albero.
Prop Drilling: l'anti-pattern di passare dati attraverso molti livelli intermedi di componenti che non li usano direttamente.
Context API: soluzione nativa per il prop drilling, ideale per dati stabili e poco mutevoli (temi, auth, lingua).
Redux: architettura centralizzata basata su un singolo store, actions e reducers puri. Oggi si usa Redux Toolkit (RTK).
Zustand / Jotai: librerie moderne con boilerplate minimo. Zustand usa un approccio a store (simile a Redux), Jotai usa gli atomi.
Server State: dati provenienti dal backend. Strumenti come React Query o SWR gestiscono cache, fetching e sincronizzazione separatamente dallo stato UI.
Immutabilità: lo stato non va mai modificato per assegnazione diretta (state.x = 1), ma ricreato tramite copia (es. spread operator).
Q: Quando usi Context API e quando Redux/Zustand?R: Uso Context per dati semplici e stabili come il tema o l'utente loggato. Passo a Zustand o Redux quando ho stati complessi, frequenti aggiornamenti parziali e mi serve un buon time-travel debugging.
Q: Come previeni i render inutili causati dallo stato globale?R: Estraggo solo i dati strettamente necessari usando selettori precisi. In Redux uso useSelector, in Zustand passo una funzione di selezione. Se serve, avvolgo i componenti complessi in React.memo.
Q: Perché lo stato in React o Redux deve essere immutabile?R: Perché per capire se c'è stata una modifica viene usata la strict equality (===). Se muto l'oggetto direttamente il riferimento non cambia e il framework non fa scattare il re-render.
Mettere tutto nello stato globale: dati effimeri come il testo di un form input dovrebbero restare nello stato locale.
Mutare lo stato direttamente (es. state.items.push(newItem)) rompendo il ciclo di re-render e il time-travel debugging.
Usare Context API per stati che cambiano molto velocemente, causando il re-render a cascata di tutti i componenti che consumano il context.
// Esempio di store Zustand con TypeScript
import { create } from 'zustand'
interface CartState {
items: string[]
addItem: (item: string) => void
}
export const useCartStore = create<CartState>((set) => ({
items: [],
// Aggiornamento immutabile dello stato
addItem: (item) => set((state) => ({ items: [...state.items, item] })),
}))
// Uso in un componente: seleziono solo la funzione, evito render inutili
// const addItem = useCartStore((state) => state.addItem)
[ ] Architettura Flux e differenze con MVC
[ ] Configurazione base di Redux Toolkit (slice e store)
[ ] Pattern ad atomi in Jotai o Recoil