useEffect di React non è un cestino. È un contratto con la realtà

Per gestire questi casi, React fornisce l’hook useEffect, pensato appositamente per isolare tutto ciò che rompe la purezza del render in un punto preciso e dichiarativo. L’effetto viene eseguito dopo il render, garantendo che la UI sia già stata costruita e che le interazioni con il mondo esterno avvengano in modo controllato.
Nel seguito approfondiremo quando è opportuno usare useEffect, quali sono gli errori più comuni e come progettare lo stato in modo da ridurre al minimo la dipendenza da effetti. Scopriremo anche le best‑practice per le dipendenze, il side effect e il cleanup di risorse esterne, fornendo esempi pratici e consigli SEO‑friendly per migliorare la qualità del tuo codice React.
Come funziona useEffect in React
useEffect è un hook che accetta due argomenti: una funzione da eseguire dopo il render e un array facoltativo di dipendenze. Quando l’array è vuoto ([]), l’effetto viene eseguito una sola volta, subito dopo il montaggio del componente, similmente a componentDidMount nelle classi.
Questo meccanismo è ideale per inizializzare risorse, impostare listener o avviare richieste di rete. La chiave è che l’effetto non influisce sul render corrente, ma sincronizza il componente con il mondo esterno una volta che il DOM è pronto.
Perché tutto finisce dentro useEffect
Il motivo per cui useEffect diventa un “bidone dell’indifferenziata” è la sua immediatezza: se abbiamo un problema di sincronizzazione tra stati, basta aggiungere un useEffect. Se dobbiamo calcolare qualcosa quando cambia una prop, lo facciamo con un altro effetto. Quando aggiorniamo uno stato in risposta a un altro, usiamo ancora useEffect.
All’inizio sembra una soluzione pratica, ma col tempo il componente può trasformarsi in un intreccio di effetti che si attivano a catena. Non c’è più un flusso chiaro di dati, ma una rete di reazioni dove una piccola modifica può innescare più effetti, alcuni dei quali non previsti, portando a chiamate API inutili o a UI instabili.
Il vero problema è un design dello stato sbagliato: se un valore può essere derivato da altri stati o da props, non dovrebbe essere gestito come stato separato, ma calcolato direttamente nel render. Inserire tale valore in useEffect crea una duplicazione della verità, aumentando il rischio di bug difficili da tracciare.
Stato derivato vs effetto: un esempio pratico
Spesso si crea uno stato aggiuntivo per tenere traccia di un valore che potrebbe essere calcolato al volo. In questi casi, useEffect è superfluo e complica il codice.
Qui doubled è semplicemente il risultato di un calcolo basato su count. Non c’è bisogno di memorizzarlo nello stato né di sincronizzarlo con un effetto: il render puro lo ricava automaticamente. Questo approccio riduce la complessità, evita dipendenze inutili e rende il componente più leggero e performante.
Che cosa sono i side effect in pratica
Il termine side effect non è un eufemismo per “codice fastidioso”, ma indica qualsiasi operazione che va oltre il semplice calcolo del JSX. Sono azioni che toccano il mondo esterno a React: richieste HTTP, subscription a eventi, timer, accesso a localStorage, o manipolazione diretta del DOM tramite librerie esterne.
Quando si hanno questi effetti collaterali, useEffect è lo strumento consigliato perché React garantisce che il render sia già completato, permettendo di operare in un contesto stabile. Questo evita inconsistenti aggiornamenti della UI durante il ciclo di rendering e mantiene separata la logica di visualizzazione da quella di interazione con l’esterno.
Fetch di dati con useEffect
Un caso d’uso tipico è il recupero di dati da un’API remota. L’effetto si esegue una sola volta al montaggio, popola lo stato locale e la UI si aggiorna automaticamente.
L’aspetto fondamentale è capire che useEffect non è pensato per reagire a tutti i cambiamenti, ma per sincronizzare il componente con una risorsa esterna. Se l’effetto serve solo a impostare un altro stato interno, è probabile che la logica possa essere spostata nel render puro, semplificando notevolmente il componente.
Le dipendenze di useEffect: il riflettore di React
L’array delle dipendenze è la linea di demarcazione tra chi ha compreso l’uso di useEffect e chi lo utilizza a tentoni. Qui non si tratta di un semplice suggerimento, ma di una dichiarazione di intenti: si comunica a React quali valori, se modificati, devono far rieseguire l’effetto.
Se si omette una dipendenza o se la si dichiara in modo errato, React non genera un errore immediato, ma accumula un debito tecnico che può manifestarsi in comportamenti intermittenti. Questi bug sono subdoli perché non rompono l’applicazione subito, ma causano inconsistenze difficili da individuare, soprattutto in scenari con sequenze di eventi complesse.
Progettare lo stato invece di appoggiarsi agli effetti
La differenza tra un codice React solido e uno fragile non è quante volte si usa useEffect, ma quante volte si riesce a evitarlo. Quando lo stato è modellato correttamente, molte operazioni “succedono da sole” durante il render: valori derivabili, calcoli basati su props e stati, e aggiornamenti della UI descritti esplicitamente.
Più la logica è spostata nel render puro, meno si dipende da effetti temporizzati o asincroni. Questo approccio riduce la probabilità di bug legati al tempo, migliora la manutenibilità e rende le componenti più facili da testare, perché il risultato è deterministico dato lo stesso input.
Benefici di un uso corretto di useEffect
Quando useEffect è impiegato in modo consapevole, racconta una storia chiara: il componente si sincronizza con una risorsa esterna, si iscrive a un evento, e rimuove gli ascoltatori quando non servono più. Questa struttura rende il codice onesto e trasparente, separando la descrizione dell’interfaccia da quella delle interazioni con il mondo fuori da React.
In questo esempio, l’effetto esplicita il suo scopo (monitorare il resize) e ne gestisce il cleanup. Il risultato è un componente più leggibile e affidabile, perché le dipendenze e le risorse sono dichiarate in modo esplicito, evitando sorprese nascoste dentro il render.
Alla fine, useEffect non è il nemico: l’uso pigro e non pianificato lo è. È uno strumento potente, ma va utilizzato con una progettazione attenta dei dati e dello stato. Così facendo, il codice rimarrà pulito, scalabile e pronto a crescere senza crollare sotto il peso di effetti non controllati.