-
Notifications
You must be signed in to change notification settings - Fork 19
/
use-intersection-observer.ts
50 lines (40 loc) · 1.23 KB
/
use-intersection-observer.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
import * as React from 'react'
export type IntersectionObserverOptions = IntersectionObserverInit & {
triggerOnce?: boolean
}
export const createObserver = <T = HTMLElement>(
elm: T,
options: IntersectionObserverOptions,
cb: (entry: IntersectionObserverEntry) => void
) => {
const handleObserve: IntersectionObserverCallback = ([element], observer) => {
if (element?.isIntersecting) {
if (options.triggerOnce) {
observer.unobserve(elm as unknown as Element)
}
cb(element)
}
}
const observer = new IntersectionObserver(handleObserve, options)
observer.observe(elm as unknown as Element)
return observer
}
export const useIntersectionObserver = <T = HTMLElement>(
options: IntersectionObserverOptions
): [React.RefObject<T>, { inView: boolean }] => {
const ref = React.useRef<T>(null)
const [inView, setInView] = React.useState(false)
React.useEffect(() => {
const elementToObserve = ref.current
if (!elementToObserve) return
const observer = createObserver(elementToObserve, options, (element) => {
setInView(() => {
return element.isIntersecting
})
})
return () => {
observer.disconnect()
}
}, [options])
return [ref, { inView }]
}