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
3function useEventListener<T extends HTMLElement = HTMLDivElement>(
4 eventName: keyof WindowEventMap,
5 handler: (event: Event) => void,
6 element?: RefObject<T>,
7) {
8 // Create a ref that stores handler
9 const savedHandler = useRef<(event: Event) => void>()
10
11 useEffect(() => {
12 // Define the listening target
13 const targetElement: T | Window = element?.current || window
14 if (!(targetElement && targetElement.addEventListener)) {
15 return
16 }
17
18 // Update saved handler if necessary
19 if (savedHandler.current !== handler) {
20 savedHandler.current = handler
21 }
22
23 // Create event listener that calls handler function stored in ref
24 const eventListener = (event: Event) => {
25 // eslint-disable-next-line no-extra-boolean-cast
26 if (!!savedHandler?.current) {
27 savedHandler.current(event)
28 }
29 }
30
31 targetElement.addEventListener(eventName, eventListener)
32
33 // Remove event listener on cleanup
34 return () => {
35 targetElement.removeEventListener(eventName, eventListener)
36 }
37 }, [eventName, element, handler])
38}
39
40export 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}

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