useEventListener()
Use EventListener with simplicity by React Hook.
Supports Window
, Element
and Document
and custom events with almost the same parameters as the native addEventListener
options. See examples below.
The Hook
1import { RefObject, useEffect, useRef } from 'react'23import { useIsomorphicLayoutEffect } from 'usehooks-ts'45// MediaQueryList Event based useEventListener interface6function useEventListener<K extends keyof MediaQueryListEventMap>(7 eventName: K,8 handler: (event: MediaQueryListEventMap[K]) => void,9 element: RefObject<MediaQueryList>,10 options?: boolean | AddEventListenerOptions,11): void1213// Window Event based useEventListener interface14function useEventListener<K extends keyof WindowEventMap>(15 eventName: K,16 handler: (event: WindowEventMap[K]) => void,17 element?: undefined,18 options?: boolean | AddEventListenerOptions,19): void2021// Element Event based useEventListener interface22function useEventListener<23 K extends keyof HTMLElementEventMap,24 T extends HTMLElement = HTMLDivElement,25>(26 eventName: K,27 handler: (event: HTMLElementEventMap[K]) => void,28 element: RefObject<T>,29 options?: boolean | AddEventListenerOptions,30): void3132// Document Event based useEventListener interface33function useEventListener<K extends keyof DocumentEventMap>(34 eventName: K,35 handler: (event: DocumentEventMap[K]) => void,36 element: RefObject<Document>,37 options?: boolean | AddEventListenerOptions,38): void3940function useEventListener<41 KW extends keyof WindowEventMap,42 KH extends keyof HTMLElementEventMap,43 KM extends keyof MediaQueryListEventMap,44 T extends HTMLElement | MediaQueryList | void = void,45>(46 eventName: KW | KH | KM,47 handler: (48 event:49 | WindowEventMap[KW]50 | HTMLElementEventMap[KH]51 | MediaQueryListEventMap[KM]52 | Event,53 ) => void,54 element?: RefObject<T>,55 options?: boolean | AddEventListenerOptions,56) {57 // Create a ref that stores handler58 const savedHandler = useRef(handler)5960 useIsomorphicLayoutEffect(() => {61 savedHandler.current = handler62 }, [handler])6364 useEffect(() => {65 // Define the listening target66 const targetElement: T | Window = element?.current ?? window6768 if (!(targetElement && targetElement.addEventListener)) return6970 // Create event listener that calls handler function stored in ref71 const listener: typeof handler = event => savedHandler.current(event)7273 targetElement.addEventListener(eventName, listener, options)7475 // Remove event listener on cleanup76 return () => {77 targetElement.removeEventListener(eventName, listener, options)78 }79 }, [eventName, element, options])80}8182export default useEventListener
Usage
1import { useRef } from 'react'23import { useEventListener } from 'usehooks-ts'45export default function Component() {6 // Define button ref7 const buttonRef = useRef<HTMLButtonElement>(null)8 const documentRef = useRef<Document>(document)910 const onScroll = (event: Event) => {11 console.log('window scrolled!', event)12 }1314 const onClick = (event: Event) => {15 console.log('button clicked!', event)16 }1718 const onVisibilityChange = (event: Event) => {19 console.log('doc visibility changed!', {20 isVisible: !document.hidden,21 event,22 })23 }2425 // example with window based event26 useEventListener('scroll', onScroll)2728 // example with document based event29 useEventListener('visibilitychange', onVisibilityChange, documentRef)3031 // example with element based event32 useEventListener('click', onClick, buttonRef)3334 return (35 <div style={{ minHeight: '200vh' }}>36 <button ref={buttonRef}>Click me</button>37 </div>38 )39}
See a way to make this page better?
Edit there »