UNPKG

2.47 kBJavaScriptView Raw
1import { useState } from 'react';
2import useStableMemo from './useStableMemo';
3import useEffect from './useIsomorphicEffect';
4import useEventCallback from './useEventCallback';
5
6/**
7 * Setup an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) on
8 * a DOM Element that returns it's entries as they arrive.
9 *
10 * @param element The DOM element to observe
11 * @param init IntersectionObserver options with a notable change,
12 * unlike a plain IntersectionObserver `root: null` means "not provided YET",
13 * and the hook will wait until it receives a non-null value to set up the observer.
14 * This change allows for easier syncing of element and root values in a React
15 * context.
16 */
17
18/**
19 * Setup an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) on
20 * a DOM Element. This overload does not trigger component updates when receiving new
21 * entries. This allows for finer grained performance optimizations by the consumer.
22 *
23 * @param element The DOM element to observe
24 * @param callback A listener for intersection updates.
25 * @param init IntersectionObserver options with a notable change,
26 * unlike a plain IntersectionObserver `root: null` means "not provided YET",
27 * and the hook will wait until it receives a non-null value to set up the observer.
28 * This change allows for easier syncing of element and root values in a React
29 * context.
30 *
31 */
32
33function useIntersectionObserver(element, callbackOrOptions, maybeOptions) {
34 let callback;
35 let options;
36 if (typeof callbackOrOptions === 'function') {
37 callback = callbackOrOptions;
38 options = maybeOptions || {};
39 } else {
40 options = callbackOrOptions || {};
41 }
42 const {
43 threshold,
44 root,
45 rootMargin
46 } = options;
47 const [entries, setEntry] = useState(null);
48 const handler = useEventCallback(callback || setEntry);
49
50 // We wait for element to exist before constructing
51 const observer = useStableMemo(() => root !== null && typeof IntersectionObserver !== 'undefined' && new IntersectionObserver(handler, {
52 threshold,
53 root,
54 rootMargin
55 }), [handler, root, rootMargin, threshold && JSON.stringify(threshold)]);
56 useEffect(() => {
57 if (!element || !observer) return;
58 observer.observe(element);
59 return () => {
60 observer.unobserve(element);
61 };
62 }, [observer, element]);
63 return callback ? undefined : entries || [];
64}
65export default useIntersectionObserver;
\No newline at end of file