JAVASCRIPT

Attach and Cleanup Event Listeners with `useEventListener`

Discover how to create a robust `useEventListener` React hook to easily attach global event listeners to the window, document, or a DOM element with automatic cleanup.

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);

    // Clean up on unmount
    return () => {
      element.removeEventListener(eventName, eventListener);
    };
  }, [eventName, element]); // Re-run if eventName or element changes

  return savedHandler;
}

export default useEventListener;

// Example Usage:
// import React, { useRef } from 'react';
// function MyComponent() {
//   const handleScroll = () => {
//     console.log('Window scrolled!', window.scrollY);
//   };
//
//   useEventListener('scroll', handleScroll, typeof window !== 'undefined' ? window : null);
//
//   const myDivRef = useRef();
//   const handleClickDiv = () => {
//     console.log('Div clicked!');
//   };
//   // Ensure myDivRef.current is available when attaching listener
//   useEventListener('click', handleClickDiv, myDivRef.current);
//
//   return <div ref={myDivRef} style={{ height: '200px', width: '200px', border: '1px solid black', overflow: 'auto' }}>
//            Scroll me or click me
//          </div>;
// }
How it works: The `useEventListener` hook provides a clean way to attach event listeners to the `window`, `document`, or a specific DOM element, with automatic cleanup when the component unmounts. It uses a `useRef` to store the latest event handler function, preventing unnecessary re-creation of the event listener if only the handler changes, and an `useEffect` to manage the lifecycle of adding and removing the listener, ensuring proper resource management.

Need help integrating this into your project?

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

Hire DigitalCodeLabs