Created
August 2, 2021 07:58
-
-
Save lexeeech/1a4edc01f1c46cf918ccb3cc4502e66a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useRef } from 'react'; | |
export function useEventListener<K extends keyof WindowEventMap>( | |
eventName: K, | |
handler: (ev: WindowEventMap[K]) => any, | |
element = global, | |
) { | |
// Create a ref that stores handler | |
const savedHandler = useRef<(ev: WindowEventMap[K]) => any>(); | |
// 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 deps array ... | |
// ... and potentially cause effect to re-run every render. | |
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: WindowEventMap[K]) => | |
savedHandler.current !== undefined && savedHandler.current(event); | |
// Add event listener | |
element.addEventListener(eventName, eventListener); | |
// Remove event listener on cleanup | |
// eslint-disable-next-line consistent-return | |
return () => { | |
element.removeEventListener(eventName, eventListener); | |
}; | |
}, | |
[eventName, element], // Re-run if eventName or element changes | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment