JAVASCRIPT

React `useEventListener` Hook for Global Events

Safely add and remove event listeners to the window, document, or any ref in React with the `useEventListener` hook, preventing memory leaks.

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 to always have the latest handler ...
  // ... without us having to pass it in a dependency array ...
  // ... and potentially cause an effect to re-run.
  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(
    () => {
      // Make sure element supports addEventListener
      // On assert, element will be a type that it's guaranteed to have 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
  );
}

// Example Usage:
// function MousePosition() {
//   const [coords, setCoords] = useState({ x: 0, y: 0 });
//   const handler = ({ clientX, clientY }) => {
//     setCoords({ x: clientX, y: clientY });
//   };
//   useEventListener('mousemove', handler);
//
//   return (
//     <p>Mouse Position: ({coords.x}, {coords.y})</p>
//   );
// }
How it works: The `useEventListener` hook simplifies the process of adding and removing event listeners to the `window`, `document`, or a specific DOM element referenced by a `ref`. It ensures that the event listener is properly attached when the component mounts and cleaned up when it unmounts, preventing memory leaks. It also uses a `ref` for the handler function, ensuring that the effect doesn't unnecessarily re-run if the handler function identity changes.

Need help integrating this into your project?

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

Hire DigitalCodeLabs