sandervspl

useEventListener hook

Dec 8th, 2021
737
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { useEffect, useRef } from 'react';
  2.  
  3. export function useEventListener<K extends keyof HTMLElementEventMap>(
  4.   eventName: K,
  5.   handler: (e: HTMLElementEventMap[K]) => void,
  6.   element: HTMLElement | Window | null = window,
  7. ): void {
  8.   // Create a ref that stores handler
  9.   const savedHandler = useRef<any>(); // eslint-disable-line @typescript-eslint/no-explicit-any
  10.  
  11.   // Update ref.current value if handler changes.
  12.   // This allows our effect below to always get latest handler
  13.   // without us needing to pass it in effect deps array
  14.   // and potentially cause effect to re-run every render.
  15.   useEffect(() => {
  16.     savedHandler.current = handler;
  17.   }, [handler]);
  18.  
  19.   useEffect(() => {
  20.     // Make sure element supports addEventListener
  21.     const isSupported = element && element.addEventListener;
  22.     if (!isSupported) return;
  23.  
  24.     // Create event listener that calls handler function stored in ref
  25.     // eslint-disable-next-line @typescript-eslint/no-explicit-any
  26.     const eventListener = (event: any) => savedHandler.current(event);
  27.  
  28.     // Add event listener
  29.     element?.addEventListener(eventName, eventListener);
  30.  
  31.     // Remove event listener on cleanup
  32.     return () => {
  33.       element?.removeEventListener(eventName, eventListener);
  34.     };
  35.   }, [eventName, element]); // Re-run if eventName or element changes
  36. }
  37.  
RAW Paste Data