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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs