React: event handler e gli hook
Premessa
Nello svilppo con React solitamente gli eventi legati ad interazioni del mouse o della tastiera sono gestiti direttamente utilizzando gli attributi dei componenti.
Capita però a volte di dover gestire eventi particolari ad esempio quelli legati all’oggetto window
, come gli eventi di resize
o scroll
. Vedremo quindi come gestirli in modo corretto.
Gli event handler
Possiamo scrivere dei classici event handler di React.
Ad esempio volendo gestire sia l’evento di click che di doppio click su un div
possiamo scrivere qualcosa di questo tipo:
<div
onClick={handleClick}
onDoubleClick={event => handleDblClick(event)}
>
...
</div>
Nell’esempio di cui sopra troviamo specificati due gestori degli eventi in due modi diversi. Entrambi sono validi e hanno comportamento simile.
Quando specifichiamo l’handler nella prima forma stiamo dicendo “quando si scatena l’evento di click invoca handleClick
passandogli come parametri tutti quelli che l’attributo onClick
mette a disposizione. Nella seconda forma invece diciamo di invocare l'event handler
handleDblClickpassando solo il parametro
event`.
Buona prassi è utilizzare in primis le proprietà dei componenti quando scriviamo degli event handler.
Quando invece sviluppiamo degli event handler classici in JavaScript solitamente scriviamo qualcosa di questo tipo:
function handleResize() {
console.log('Nuove dimensioni: ', window.innerWidth, 'x', window.innerHeight)
}
window.addEventListener('resize', handleResize)
Nell’esempio specifico prima un event handler, ovvero una fuzione da eseguire quando si scatena un determinato evento.
Questo ovviamente non basta. Abbiamo solo scritto la funzione, dobbiamo ancora specificare quando deve essere eseguita. Lo possiamo fare con l’ultima riga: all’oggetto window
attacchiamo un event listener che all’evento resize
invoca la funzione handleResize
passandole tutti i parametri disponibili.
Problema, siamo in una Single Page Application
In React dobbiamo però prestare attenzione. Siamo all’interno di una SPA ovvero una Single Page Application. Non usciamo mai da un pagina veramente.
Gli event handler a livello globale che registrate, i timer, ecc rimangono attivi salvo che voi non li terminiate.
Il rischio è oltretutto che ad ogni mount del componente, registriate nuovi event handler copia.
Registriamo l’event handler con useEffect
Possimo usare l’hook useEffect per attivare l’event listener in fase di mount del componente e poi disattivarlo quando il componente stesso viene smontato. Questo ci assicura che il codice viene eseeguito solo quando necessario.
Il codice che possiamo scrivere è come segue:
import { useEffect } from "react";
function handleResize() {
console.log("Nuove dimensioni: ", window.innerWidth, "x", window.innerHeight);
}
export default function App() {
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
}
}, []);
return (
<div className="App">
<h1>Your Component</h1>
</div>
);
}
Dichiaro la funzione handleResize
esternamente al componente per evitare che sia generata ogni volta che viene renderizzato.
Se dovessi usare hook invece costretto a crearla internamente, eventualmente ottimizzandola con un hook useCallback
.
Nel componente poi uso il l’hook useEffect
senza le dipendenze (notate []
come ultimo parametro) per fare in modo che il codice sia eseguito solo in fase di mount, ovvero quando il componente è aggiunto al DOM.
Dichiaro poi un return
che verrà eseguito solo in fase di unmount del componente. Questa è una funzione chiamata di cleanup.
Trovate l’esempio al seguente link.
Conclusioni
Come avete visto possiamo correttamente registrare degli event handler in un’applicazione React. L’importante è ricordasi di rimuoverlo quando non più necessario, come ad esempio quando il componente viene smontato. Non è l’unico modo per farlo ma è sicuramente tra i più frequenti.