State usando React e vi sembra che i componenti si ri-renderizzino senza motivo? O vi capita di leggere uno stato vecchio dentro un effetto? Siamo passati da classi a funzioni, ma gli hook non sono magia: sono strumenti precisi. Noi, di Meteora Web, li usiamo ogni giorno nei nostri progetti Laravel + React e abbiamo visto gli stessi errori ripetersi. In questa guida vi portiamo al sodo: cosa fa ogni hook, quando usarlo e — più importante — quando NO. Partiamo dal problema concreto.
useState — Lo stato reattivo che spesso usiamo male
useState gestisce lo stato locale. Sembra banale, ma il 90% dei bug deriva da aggiornamenti asincroni e valori obsoleti.
Aggiornamenti funzionali: perché usarli sempre
Quando il nuovo stato dipende dal precedente, passate una funzione, non un valore diretto.
// ❌ Sbagliato: se clicchi due volte velocemente, perdi un incremento
setCount(count + 1);
// ✅ Corretto: la funzione riceve sempre l'ultimo valore
setCount(prev => prev + 1);
Lo stesso vale per oggetti e array: non mutate lo stato, create una copia.
Stato iniziale “costoso” — la callback lazy
Se calcolare lo stato iniziale richiede tempo (es. lettura da localStorage), passate una funzione. React la esegue solo al primo render.
const [data, setData] = useState(() => {
const saved = localStorage.getItem('myData');
return saved ? JSON.parse(saved) : [];
});
useEffect — L’effetto collaterale sotto controllo
useEffect esegue codice dopo il render. Ma se non capite le dipendenze, create loop infiniti o mancate aggiornamenti.
L’array delle dipendenze — la regola del pollice
Includete TUTTE le variabili (stato, props, funzioni) usate dentro l’effetto. Se omettete una dipendenza, l’effetto lavora su un valore “vecchio” — lo stale closure.
Cleanup — liberare risorse
Ogni volta che sottoscrivete eventi, timer o WebSocket, restituite una funzione di cleanup.
useEffect(() => {
const timer = setInterval(() => console.log('tick'), 1000);
return () => clearInterval(timer); // pulizia
}, []);
Non farlo causa memory leak e comportamenti imprevedibili.
useEffect per fetch: pattern corretto
Un errore comune: dimenticare il flag cancelled per evitare setState su componente smontato.
useEffect(() => {
let cancelled = false;
fetch('/api/data')
.then(res => res.json())
.then(data => { if (!cancelled) setData(data); });
return () => { cancelled = true; };
}, []);
useRef — Il contenitore che non forza re-render
useRef è un oggetto mutabile che sopravvive ai render ma non li scatena. Due usi principali:
Riferimento al DOM
const inputRef = useRef(null);
// dopo il render: inputRef.current.focus();
Memorizzare valori senza causare re-render
Perfetto per tenere traccia di timer ID, valori precedenti, o dati che non devono aggiornare l’UI.
const prevCountRef = useRef();
useEffect(() => { prevCountRef.current = count; });
const prevCount = prevCountRef.current;
In pratica è come un “diario privato” del componente: scrivete, leggete, ma nessuno viene notificato.
useMemo — Memoizzazione di valori costosi
useMemo restituisce un valore memorizzato che ricalcola solo quando le dipendenze cambiano. Usatelo per calcoli pesanti (es. filtrare mille elementi, ordinare, formattare dati).
const filteredList = useMemo(
() => items.filter(item => item.active),
[items]
);
Attenzione: non memoizzate a caso. useMemo ha un costo di memoria. Il suo vero valore è evitare ricalcoli inutili su liste grandi o operazioni lente.
Analogia contabile: come un bilancio preventivo che rielabori solo quando cambiano le voci di entrata. Se non cambiano, usi l’ultima versione.
useCallback — Funzioni stabili per evitare re-render a catena
useCallback restituisce la stessa funzione finché le dipendenze non cambiano. Serve principalmente quando passate funzioni a componenti figli ottimizzati con React.memo.
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
return ;
Senza useCallback, a ogni render del padre viene creata una nuova funzione, il figlio con React.memo si ri-renderizza comunque (perché la reference cambia).
Regola pratica: usate useCallback solo quando avete un componente figlio che è ottimizzato con React.memo o PureComponent. In tutti gli altri casi, è rumore.
Mettere tutto insieme — Un esempio reale
Ecco un mini-form che usa tutti e cinque gli hook:
function SearchForm({ onSubmit }) {
const [query, setQuery] = useState('');
const inputRef = useRef(null);
const debouncedQuery = useDebounce(query, 300); // hook custom
const handleSubmit = useCallback((e) => {
e.preventDefault();
onSubmit(debouncedQuery);
}, [debouncedQuery, onSubmit]);
const searchResults = useMemo(() => {
if (!debouncedQuery) return [];
return expensiveSearch(debouncedQuery);
}, [debouncedQuery]);
useEffect(() => {
if (query) inputRef.current?.focus();
}, [query]);
return (
);
}
Vedete: ogni hook ha uno scopo preciso. Nessuno è decorativo.
Errori comuni — La lista nera
- Stale closure: usare una variabile dentro useEffect senza metterla nelle dipendenze. La soluzione è includerla o usare useRef se è intenzionale.
- Oggetti/array come dipendenze: React confronta per reference, non per valore. Se create un nuovo oggetto a ogni render, l’effetto o memo si riesegue sempre. Usate
useMemoper stabilizzare. - useMemo/useCallback prematuri: non ottimizzate prima di aver misurato. Prima fate funzionare, poi profiliate.
- useEffect senza cleanup: sottoscrizioni, timer, listener — sempre cleanup.
In sintesi — Cosa fare adesso
- Rivedete i vostri useEffect: controllate se tutte le variabili sono nell’array delle dipendenze.
- Aggiungete cleanup a ogni sottoscrizione (setInterval, addEventListener, fetch cancellato).
- Sostituite useState diretti con
setCount(prev => prev + 1)nei casi di aggiornamenti basati sul precedente. - Analizzate i re-render con React DevTools: dove vedete nodi inutili, valutate useMemo/useCallback su componenti figli con React.memo.
- Eliminate useMemo/useCallback che non servono: se non migliorano le performance, toglieteli.
Noi, di Meteora Web, consigliamo sempre di scrivere codice pulito prima di ottimizzare. Gli hook sono strumenti potenti se usati con consapevolezza. Se volete approfondire, il sito ufficiale React è la fonte migliore.
Sponsored Protocol