JAVASCRIPT
Attach and Clean Up Event Listeners with `useEventListener` React Hook
Create a reusable `useEventListener` React hook to easily attach and remove DOM event listeners, improving component lifecycle management and preventing memory leaks.
import React, { useEffect, useRef } from 'react';
function useEventListener(eventName, handler, element = window) {
// Create a ref that stores handler
const savedHandler = useRef();
// Update ref.current value if handler changes.
// This allows our effect below to always get latest handler ...
// ... without resetting timer.
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(() => {
// Make sure element supports addEventListener
// On modern browsers, element.addEventListener set to undefined for a reason
// for example, useEventListener('resize', handler, document.querySelector('div')) does not make sense
const isSupported = element && element.addEventListener;
if (!isSupported) {
return;
}
// Create event listener that calls handler function stored in ref
const eventListener = (event) => savedHandler.current(event);
// Add event listener
element.addEventListener(eventName, eventListener);
// Remove event listener on cleanup
return () => {
element.removeEventListener(eventName, eventListener);
};
}, [eventName, element]); // Re-run if eventName or element changes
}
// Example Usage:
function MyComponent() {
const [coords, setCoords] = React.useState({ x: 0, y: 0 });
const handleMouseMove = React.useCallback((event) => {
setCoords({ x: event.clientX, y: event.clientY });
}, []);
useEventListener('mousemove', handleMouseMove);
return (
<div>
Mouse position: ({coords.x}, {coords.y})
</div>
);
}
How it works: The `useEventListener` hook simplifies attaching and cleaning up event listeners. It accepts an event name, a handler function, and an optional target element (defaults to `window`). It uses `useRef` to maintain a stable reference to the handler, ensuring that the event listener doesn't need to be re-attached unnecessarily when the handler logic changes. `useEffect` then handles adding and removing the listener during the component's lifecycle.