# Le regole degli hook, spiegate con i casi che rompono

Gli hook si chiamano solo al livello superiore di un componente o di un hook: se l’ordine cambia fra due render, React legge lo stato sbagliato.

> Pagina: https://ui.eneawork.it/blog/react-hooks-regole
> Markdown: https://ui.eneawork.it/blog/react-hooks-regole.md

*2026-11-01*

Le regole degli hook sono due: chiamali solo al livello superiore del componente, e solo dentro funzioni React. Condizioni, cicli e callback annidate rompono l’ordine su cui React costruisce lo stato.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, misurati da /api/stats il 1 novembre 2026. La cifra viene da una query all’endpoint, non da una stima: conta i record pubblicati e non dice quanti usino questa API correttamente.

## Perché l’ordine conta

React non salva lo stato per nome. Ogni componente porta una lista ordinata di slot: il primo useState occupa lo slot zero, il secondo lo slot uno, e al render successivo React rilegge la lista nella stessa sequenza. Se una condizione salta una chiamata, tutti gli hook dopo di lei scivolano di una posizione e leggono il valore di un altro.

## Il caso che rompe più spesso

Un’uscita anticipata prima di un hook è il modo più comune di violare la regola senza accorgersene: il primo render non arriva alla chiamata, il secondo sì.

function Profile({ user, loading }) { const [open, setOpen] = useState(false); if (loading) return Loading; // first render stops here const [tab, setTab] = useState("info"); // slot 1 appears only later return ( setOpen(!open)}>{user.name} {open && } ); }

Sposta il return dopo tutti gli hook, oppure estrai la parte condizionale in un componente figlio: il figlio viene montato solo quando serve, e i suoi hook partono con lui, in ordine.

## Gli altri tre casi

## Il controllo automatico

Il plugin ESLint ufficiale riconosce i tre casi e li segnala durante il lint. Si installa come dipendenza di sviluppo e si attiva in una configurazione flat:

npm install --save-dev eslint eslint-plugin-react-hooks

import reactHooks from "eslint-plugin-react-hooks"; export default [ { files: ["src/**/*.{js,jsx,ts,tsx}"], plugins: { "react-hooks": reactHooks }, rules: reactHooks.configs.recommended.rules, }, ];

Con il file eslint.config.js nella radice, npx eslint src blocca il merge se qualcuno rimette un hook dentro un if. Il plugin è distribuito con licenza MIT, come React.

## Le stesse regole dentro un custom hook

Un custom hook è una funzione che inizia con use e chiama altri hook: le regole valgono identiche, perché React non vede il confine della funzione. Il prefisso non è decorazione, è il segnale che il linter usa per sapere che quella funzione può contenere hook.

Per questo un custom hook non si chiama dentro un if del componente che lo usa: la condizione deve stare al suo interno, dove il chiamante non deve saperne nulla.

## Record vivi nel catalogo

Nel catalogo ogni componente React usa hook nei propri file: list-item per una riga di lista, expandable-tabs per lo stato di una tab. Entrambi sono record pubblicati tra i 111.985 componenti e i 1.556 blocchi.

## La limitazione

Le regole garantiscono l’ordine delle chiamate, non la correttezza delle dipendenze: un useEffect con una lista sbagliata passa il linter e continua a leggere valori vecchi. Quel controllo è una regola separata e resta un avviso, non una prova.

## Dove continuare

La differenza fra i due effect è in useEffect vs useLayoutEffect; cosa cambia nella versione 19 è in React 19; il confronto con l’altro framework diffuso è in Vue 3 vs React.

## FAQ

### Perché React richiede un ordine fisso negli hook?

Perché lo stato è salvato in una lista di slot per componente, non per nome. React rilegge la lista nell’ordine di chiamata: se l’ordine cambia, ogni hook legge il valore di un altro slot.

### Posso chiamare un hook dentro un if se la condizione non cambia mai?

No. La regola è statica e il linter non può dimostrare che la condizione resta stabile: quel codice funziona finché qualcuno non cambia la condizione, e allora rompe in produzione.

### Un custom hook deve iniziare con use?

Sì, è la convenzione che il linter usa per riconoscere una funzione che può contenere hook. Senza prefisso il plugin non controlla il corpo e i chiamanti non ricevono avvisi.

### Le regole valgono anche per useMemo e useCallback?

Sì. Ogni hook consuma uno slot, quindi valgono per tutti: useState, useEffect, useMemo, useCallback, useRef e i custom hook scritti sopra di loro.

### Cosa succede se violo le regole?

Nei casi netti React lancia un errore, di solito “Rendered more hooks than during the previous render”. Nei casi ambigui non lancia nulla e mostra uno stato sbagliato, che è il guasto peggiore da diagnosticare.
