forked from facebook/react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseIntersectionObserver-fixed.js
More file actions
76 lines (61 loc) · 1.83 KB
/
useIntersectionObserver-fixed.js
File metadata and controls
76 lines (61 loc) · 1.83 KB
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
67
68
69
70
71
72
73
74
75
76
import { useRef, useCallback, useEffect, useMemo } from 'react';
function useIntersectionObserver(options = {}) {
const observerRef = useRef(null);
const callbacksRef = useRef(new Map());
// Callback function for IntersectionObserver - safely accesses refs in async context
const handleIntersect = useCallback((entries) => {
entries.forEach(entry => {
const callback = callbacksRef.current.get(entry.target.id);
if (callback) {
callback(entry.isIntersecting);
}
});
}, []);
// Create observer memoized to avoid unnecessary recreation
const observer = useMemo(() => {
if (typeof IntersectionObserver === 'undefined') {
return null;
}
return new IntersectionObserver(handleIntersect, options);
}, [handleIntersect, JSON.stringify(options)]);
// Setup and cleanup observer in effect
useEffect(() => {
if (!observer) {
return;
}
observerRef.current = observer;
return () => {
if (observerRef.current) {
observerRef.current.disconnect();
observerRef.current = null;
}
};
}, [observer]);
// Register callback for a specific element
const registerCallback = useCallback((elementId, callback) => {
callbacksRef.current.set(elementId, callback);
return () => {
callbacksRef.current.delete(elementId);
};
}, []);
// Observe an element
const observe = useCallback((element) => {
if (!observerRef.current || !element) {
return;
}
observerRef.current.observe(element);
}, []);
// Unobserve an element
const unobserve = useCallback((element) => {
if (!observerRef.current || !element) {
return;
}
observerRef.current.unobserve(element);
}, []);
return {
observe,
unobserve,
registerCallback,
};
}
export default useIntersectionObserver;