JAVASCRIPT
Simplify Event Handling with `useEventListener` Hook
Create a reusable React hook to easily attach and clean up event listeners to DOM elements, window, or document, improving component lifecycle management.
import { useRef, useEffect } from 'react';
function useEventListener(eventType, handler, element = window) {
// Create a ref that stores the handler
const savedHandler = useRef();
// Update ref.current value if handler changes.
// This allows our effect below to always get latest handler without re-running.
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(() => {
// Make sure element supports addEventListener
// On Safari, document.body.addEventListener doesn't work.
const isSupported = element && element.addEventListener;
if (!isSupported) return;
// Create event listener that calls handler function stored in ref
const eventListener = (event) => savedHandler.current(event);
element.addEventListener(eventType, eventListener);
return () => {
element.removeEventListener(eventType, eventListener);
};
}, [eventType, element]); // Re-run if eventType or element changes
}
// Example usage:
/*
function MyComponent() {
const handleKeyDown = (event) => {
console.log('Key pressed:', event.key);
};
useEventListener('keydown', handleKeyDown, document); // Listen for keydown on the document
const handleClick = (event) => {
console.log('Window clicked!');
};
useEventListener('click', handleClick); // Listen for click on window (default)
return (
<div>
<p>Press any key or click anywhere on the window.</p>
</div>
);
}
*/
How it works: The `useEventListener` hook provides a clean and declarative way to attach and automatically clean up event listeners to the `window`, `document`, or any other DOM element. It uses `useRef` to ensure the event `handler` always references the latest version without needing to re-attach the listener on every render. The `useEffect` hook handles the actual `addEventListener` and `removeEventListener` calls, simplifying event management in your components.