1 | import { useState } from 'react';
|
2 | import useStableMemo from './useStableMemo';
|
3 | import useEffect from './useIsomorphicEffect';
|
4 | import 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 |
|
33 | function 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 | }
|
65 | export default useIntersectionObserver; |
\ | No newline at end of file |