diff --git a/src/index.js b/src/index.js index 4b2cc50d..630747b5 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,7 @@ export {default as TextLink} from './TextLink'; export {default as ThemeSection} from './ThemeSection'; export {default as Time} from './Time'; export {default as useBreakpoints} from './useBreakpoints'; +export {default as useEventListener} from './useEventListener'; export {default as useInterval} from './useInterval'; export {default as ViewMoreText} from './ViewMoreText'; export {default as VisuallyHidden} from './VisuallyHidden'; diff --git a/src/useEventListener/README.mdx b/src/useEventListener/README.mdx new file mode 100644 index 00000000..9cad1745 --- /dev/null +++ b/src/useEventListener/README.mdx @@ -0,0 +1,20 @@ +--- +name: useEventListener +menu: Hooks +--- + +# useEventListener + +A simple hook that adds a global event listener & cleans up after it when the component unmounts. + +By default, the event listener is added on `document`, but you can change the element by passing a custom target element to it as the third parameter. + +## Examples + +```js +useEventListener('click', onBodyClick); +``` + +```js +useEventListener('scroll', onScroll, scrollContainerRef.current); +``` diff --git a/src/useEventListener/index.js b/src/useEventListener/index.js new file mode 100644 index 00000000..2766449b --- /dev/null +++ b/src/useEventListener/index.js @@ -0,0 +1,21 @@ +import {useEffect, useRef} from 'react'; + +function useEventListener(eventName, callback, element = document) { + const callbackRef = useRef(callback); + + useEffect(() => { + callbackRef.current = callback; + }, [callback]); + + useEffect(() => { + const currentCallback = callbackRef.current; + + element.addEventListener(eventName, currentCallback); + + return function cleanUp() { + element.removeEventListener(eventName, currentCallback); + }; + }, [eventName, element]); +} + +export default useEventListener;