JAVASCRIPT
Simplify Event Listener Management with a Custom React Hook
A flexible React hook to add and clean up event listeners efficiently on DOM elements, the window, or document, preventing memory leaks.
import { 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 us needing to pass it in effect's dependency array.
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(() => {
// Make sure element supports addEventListener
// On Server, window is undefined
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
}
export default useEventListener;
// Example Usage:
// function MyComponent() {
// const handleScroll = () => {
// console.log('Scrolled!');
// };
//
// useEventListener('scroll', handleScroll); // Attaches to window by default
//
// const buttonRef = useRef(null);
// const handleClick = () => {
// console.log('Button clicked!');
// };
//
// useEventListener('click', handleClick, buttonRef.current); // Attaches to button
//
// return (
// <div style={{ height: '200vh' }}>
// <button ref={buttonRef}>Click me</button>
// <p>Scroll down to see console logs.</p>
// </div>
// );
// }
How it works: The `useEventListener` hook provides a clean way to attach event listeners to the DOM (or any `EventTarget`) and ensures they are properly cleaned up when the component unmounts or dependencies change. It uses `useRef` to store the latest handler function, preventing unnecessary re-creation of the event listener if the handler itself is a stable function reference. This hook simplifies event management and helps prevent memory leaks.