useEventListener()

Use EventListener with simplicity by React Hook. It takes as parameters a eventName, a call-back functions (handler) and optionally a reference element. You can see above two examples using useRef and window based event.

The Hook

1import { RefObject, useEffect, useRef } from 'react'
2
3// See: https://usehooks-ts.com/react-hook/use-isomorphic-layout-effect
4import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect'
5
6function useEventListener<K extends keyof WindowEventMap>(
7 eventName: K,
8 handler: (event: WindowEventMap[K]) => void,
9): void
10function useEventListener<
11 K extends keyof HTMLElementEventMap,
12 T extends HTMLElement = HTMLDivElement,
13>(
14 eventName: K,
15 handler: (event: HTMLElementEventMap[K]) => void,
16 element: RefObject<T>,
17): void
18
19function useEventListener<
20 KW extends keyof WindowEventMap,
21 KH extends keyof HTMLElementEventMap,
22 T extends HTMLElement | void = void,
23>(
24 eventName: KW | KH,
25 handler: (
26 event: WindowEventMap[KW] | HTMLElementEventMap[KH] | Event,
27 ) => void,
28 element?: RefObject<T>,
29) {
30 // Create a ref that stores handler
31 const savedHandler = useRef(handler)
32
33 useIsomorphicLayoutEffect(() => {
34 savedHandler.current = handler
35 }, [handler])
36
37 useEffect(() => {
38 // Define the listening target
39 const targetElement: T | Window = element?.current || window
40 if (!(targetElement && targetElement.addEventListener)) {
41 return
42 }
43
44 // Create event listener that calls handler function stored in ref
45 const eventListener: typeof handler = event => savedHandler.current(event)
46
47 targetElement.addEventListener(eventName, eventListener)
48
49 // Remove event listener on cleanup
50 return () => {
51 targetElement.removeEventListener(eventName, eventListener)
52 }
53 }, [eventName, element])
54}
55
56export default useEventListener

Usage

1import React, { useRef } from 'react'
2
3import { useEventListener } from 'usehooks-ts'
4
5export default function Component() {
6 // Define button ref
7 const buttonRef = useRef<HTMLButtonElement>(null)
8
9 const onScroll = (event: Event) => {
10 console.log('window scrolled!', event)
11 }
12
13 const onClick = (event: Event) => {
14 console.log('button clicked!', event)
15 }
16
17 // example with window based event
18 useEventListener('scroll', onScroll)
19
20 // example with element based event
21 useEventListener('click', onClick, buttonRef)
22
23 return (
24 <div style={{ minHeight: '200vh' }}>
25 <button ref={buttonRef}>Click me</button>
26 </div>
27 )
28}

Edit on CodeSandbox

See a way to make this page better?
Edit there »