useState
è l’hook più basilare per gestire lo stato locale. Restituisce una coppia di valori: lo stato corrente e una funzione per aggiornarlo. È ideale per valori semplici come stringhe, numeri o booleani.
useEffect
gestisce gli effetti collaterali, come chiamate API, sottoscrizioni o manipolazione del DOM. Si esegue dopo il rendering e può essere configurato per eseguire solo quando cambiano determinate dipendenze. È l’equivalente di componentDidMount, componentDidUpdate e componentWillUnmount combinati.
useContext
permette di accedere ai valori di un Context senza bisogno di wrapper. È utile per condividere dati globali (come tema, utente autenticato) tra componenti senza passare props manualmente.
useReducer
è un’alternativa a useState per logiche di stato più complesse. Simile a Redux, accetta un reducer e restituisce lo stato corrente e una funzione dispatch. È preferibile quando hai transizioni di stato elaborate o quando il prossimo stato dipende dal precedente.
useCallback
memorizza una funzione tra i render, restituendo la stessa istanza finché le dipendenze non cambiano. È utile per ottimizzare componenti figli che si basano sull’uguaglianza referenziale.
useMemo
memorizza il risultato di un calcolo costoso, ricalcolandolo solo quando cambiano le dipendenze. A differenza di useCallback che memorizza funzioni, useMemo memorizza valori.
ATTENZIONE! è diverso da React.memo() che controlla gli aggiornamenti dei nostri props.
useRef
crea un oggetto mutabile che persiste per l’intera vita del componente. È usato principalmente per accedere agli elementi DOM o per memorizzare valori che non devono causare re-render quando cambiano.
useLayoutEffect
è simile a useEffect ma si esegue in modo sincrono dopo tutte le mutazioni del DOM e prima che il browser dipinga. È utile quando devi leggere layout e re-renderizzare sincronamente.
useImperativeHandle
personalizza il valore dell’istanza esposto ai componenti parent quando si usa ref. Va usato insieme a forwardRef.
Hooks più recenti
Ecco gli Hook più recenti introdotti in React 18 e versioni successive:
useId
genera ID univoci e stabili sia lato client che server, utile per l’accessibilità. Risolve il problema degli ID duplicati quando un componente viene renderizzato più volte o in SSR (Server-Side Rendering). Ad esempio, per collegare un input con la sua label:
const id = useId();
return (
<>
<label htmlFor={id}>Email:</label>
<input id={id} type="email" />
</>
);
useTransition
permette di contrassegnare alcuni aggiornamenti di stato come non urgenti, mantenendo l’interfaccia reattiva. Restituisce un array con un flag isPending e una funzione startTransition. È perfetto quando hai aggiornamenti pesanti che potrebbero bloccare l’UI:
const [isPending, startTransition] = useTransition();
const [input, setInput] = useState('');
const [list, setList] = useState([]);
const handleChange = (e) => {
setInput(e.target.value);
startTransition(() => {
// Aggiornamento non urgente
setList(generateHugeList(e.target.value));
});
};
useDeferredValue
è simile a useTransition ma lavora sui valori invece che sugli aggiornamenti di stato. Accetta un valore e restituisce una versione “differita” che può ritardare l’aggiornamento. È utile quando ricevi un valore da props o stato e vuoi renderizzare UI costose in modo non bloccante:
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// L'input si aggiorna immediatamente, i risultati in modo differito
return (
<>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
<SearchResults query={deferredQuery} />
</>
);
useSyncExternalStore
permette di sottoscriversi a store esterni in modo sicuro con il rendering concorrente. È principalmente per librerie di gestione dello stato, ma puoi usarlo per sottoscriverti a eventi del browser o altre fonti esterne:
const width = useSyncExternalStore(
(callback) => {
window.addEventListener('resize', callback);
return () => window.removeEventListener('resize', callback);
},
() => window.innerWidth
);
useInsertionEffect
è un Hook molto specializzato per librerie CSS-in-JS. Si esegue prima di useLayoutEffect e serve per iniettare stili nel DOM prima che vengano letti i layout. La maggior parte degli sviluppatori non lo userà mai direttamente.
La differenza principale tra useTransition e useDeferredValue è che il primo ti dà controllo su quando avviare la transizione, mentre il secondo differisce automaticamente un valore ricevuto. useTransition è più potente ma richiede di wrappare gli aggiornamenti di stato, mentre useDeferredValue è più semplice quando lavori con valori derivati.