-
Notifications
You must be signed in to change notification settings - Fork 0
/
use-intersection-observer.ts
41 lines (33 loc) · 1.3 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
import { useEffect, useRef } from 'react'
import { noop } from 'dev-disk'
type Props = IntersectionObserverInit & {
onIntersect?: (isIntersecting: boolean, entry?: IntersectionObserverEntry) => void
onEnter?: (entry?: IntersectionObserverEntry) => void
onLeave?: (entry?: IntersectionObserverEntry) => void
enabled?: boolean
}
/**
* Track intersection of a DOM element with a top-level document's viewport or with an ancestor element using Intersection Observer API.
*/
export const useIntersectionObserver = <T extends Element = HTMLDivElement>({
onIntersect = noop,
onEnter = noop,
onLeave = noop,
enabled = true,
...options
}: Props) => {
const ref = useRef<T | null>(null)
const handlerRef = useRef<Partial<Props>>()
handlerRef.current = { onIntersect, onEnter, onLeave }
useEffect(() => {
if (!enabled || !ref.current || typeof IntersectionObserver !== 'function') return
const observer = new IntersectionObserver(([entry]) => {
handlerRef.current!.onIntersect!(entry.isIntersecting, entry)
if (entry.isIntersecting) handlerRef.current!.onEnter!(entry)
else handlerRef.current!.onLeave!(entry)
}, options)
observer.observe(ref.current)
return () => observer.disconnect()
}, [enabled, options.root, options.rootMargin, options.threshold])
return ref
}