← Back to all snippets
JAVASCRIPT

Attach and Clean Up Event Listeners with useEventListener

A versatile React hook to simplify adding and removing event listeners on DOM elements or the global window/document, ensuring proper cleanup.

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 below to always get latest handler without needing to be re-run.
  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    // Make sure element supports 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
}

export default useEventListener;
How it works: The `useEventListener` hook simplifies the process of attaching and detaching event listeners to the DOM. It accepts an `eventName`, a `handler` function, and an optional `element` (defaults to `window`). It automatically adds the listener on mount and removes it on unmount, preventing memory leaks. By storing the handler in a `ref`, it ensures the event listener always uses the latest handler function without needing to re-attach on every render.

Need help integrating this into your project?

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

Hire DigitalCodeLabs