JAVASCRIPT
React `useEventListener` Hook for Global Events
Safely add and remove event listeners to the window, document, or any ref in React with the `useEventListener` hook, preventing memory leaks.
import { useRef, useEffect } 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 to always have the latest handler ...
// ... without us having to pass it in a dependency array ...
// ... and potentially cause an effect to re-run.
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(
() => {
// Make sure element supports addEventListener
// On assert, element will be a type that it's guaranteed to have addEventListener
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 MousePosition() {
// const [coords, setCoords] = useState({ x: 0, y: 0 });
// const handler = ({ clientX, clientY }) => {
// setCoords({ x: clientX, y: clientY });
// };
// useEventListener('mousemove', handler);
//
// return (
// <p>Mouse Position: ({coords.x}, {coords.y})</p>
// );
// }
How it works: The `useEventListener` hook simplifies the process of adding and removing event listeners to the `window`, `document`, or a specific DOM element referenced by a `ref`. It ensures that the event listener is properly attached when the component mounts and cleaned up when it unmounts, preventing memory leaks. It also uses a `ref` for the handler function, ensuring that the effect doesn't unnecessarily re-run if the handler function identity changes.