← Back to all snippets
JAVASCRIPT

Attach and Clean Up Event Listeners with `useEventListener` React Hook

Create a reusable `useEventListener` React hook to easily attach and remove DOM event listeners, improving component lifecycle management and preventing memory leaks.

import React, { 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 resetting timer.
  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    // Make sure element supports addEventListener
    // On modern browsers, element.addEventListener set to undefined for a reason
    // for example, useEventListener('resize', handler, document.querySelector('div')) does not make sense
    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
}

// Example Usage:
function MyComponent() {
  const [coords, setCoords] = React.useState({ x: 0, y: 0 });

  const handleMouseMove = React.useCallback((event) => {
    setCoords({ x: event.clientX, y: event.clientY });
  }, []);

  useEventListener('mousemove', handleMouseMove);

  return (
    <div>
      Mouse position: ({coords.x}, {coords.y})
    </div>
  );
}
How it works: The `useEventListener` hook simplifies attaching and cleaning up event listeners. It accepts an event name, a handler function, and an optional target element (defaults to `window`). It uses `useRef` to maintain a stable reference to the handler, ensuring that the event listener doesn't need to be re-attached unnecessarily when the handler logic changes. `useEffect` then handles adding and removing the listener during the component's lifecycle.

Need help integrating this into your project?

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

Hire DigitalCodeLabs