-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuse-event-listener.ts
66 lines (61 loc) · 1.78 KB
/
use-event-listener.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { useEffect, useRef } from 'react'
import type { RefObject } from 'react'
// Windows Event based interface
export function useEventListener<
EW extends keyof WindowEventMap
>(
event_name: EW,
callback: (event: WindowEventMap[EW]) => void,
element?: undefined,
): void
// HTML Elementh Based interface
export function useEventListener<
EH extends keyof HTMLElementEventMap,
T extends HTMLElement = HTMLDivElement,
>(
event_name: EH,
handler: (event: HTMLElementEventMap[EH]) => void,
element: RefObject<T>,
): void
// Document Event based interface
export function useEventListener<ED extends keyof DocumentEventMap>(
event_name: ED,
callback: (event: DocumentEventMap[ED]) => void,
element: RefObject<Document>,
): void
/**
* Hook to use event listener
* @param event_name - Window or Element event name
* @param callback - Callback function
* @param element - Element to attach event listener to
*/
export function useEventListener<
EW extends keyof WindowEventMap,
EH extends keyof HTMLElementEventMap,
T extends HTMLElement = HTMLDivElement,
>(
event_name: EW,
callback: (
event: WindowEventMap[EW] | HTMLElementEventMap[EH] | Event,
) => void,
element?: RefObject<T>,
) {
// Create a ref that stores handler
const handler = useRef(callback)
useEffect(() => {
// Define the listening target
const targetElement: T | Window = element?.current || window
if (!(targetElement && targetElement.addEventListener)) {
return
}
// Add event listener
const eventListener: typeof callback = (event) => {
if (!!handler?.current) handler.current(event)
}
targetElement.addEventListener(event_name, eventListener)
return () => {
targetElement.removeEventListener(event_name, eventListener)
}
}, [event_name, element, callback])
}
export default useEventListener