MCPcopy
hub / github.com/thebuilder/react-intersection-observer / useOnInView

Function useOnInView

src/useOnInView.tsx:46–149  ·  view source on GitHub ↗
(
  onIntersectionChange: IntersectionChangeEffect<TElement>,
  {
    threshold,
    root,
    rootMargin,
    trackVisibility,
    delay,
    triggerOnce,
    skip,
  }: IntersectionEffectOptions = {},
)

Source from the content-addressed store, hash-verified

44 * ```
45 */
46export const useOnInView = <TElement extends Element>(
47 onIntersectionChange: IntersectionChangeEffect<TElement>,
48 {
49 threshold,
50 root,
51 rootMargin,
52 trackVisibility,
53 delay,
54 triggerOnce,
55 skip,
56 }: IntersectionEffectOptions = {},
57) => {
58 const onIntersectionChangeRef = React.useRef(onIntersectionChange);
59 const observedElementRef = React.useRef<TElement | null>(null);
60 const observerCleanupRef = React.useRef<(() => void) | undefined>(undefined);
61 const lastInViewRef = React.useRef<boolean | undefined>(undefined);
62
63 useSyncEffect(() => {
64 onIntersectionChangeRef.current = onIntersectionChange;
65 }, [onIntersectionChange]);
66
67 // biome-ignore lint/correctness/useExhaustiveDependencies: Threshold arrays are normalized inside the callback
68 return React.useCallback(
69 (element: TElement | undefined | null) => {
70 // React <19 never calls ref callbacks with `null` during unmount, so we
71 // eagerly tear down existing observers manually whenever the target changes.
72 const cleanupExisting = () => {
73 if (observerCleanupRef.current) {
74 const cleanup = observerCleanupRef.current;
75 observerCleanupRef.current = undefined;
76 cleanup();
77 }
78 };
79
80 if (element === observedElementRef.current) {
81 return observerCleanupRef.current;
82 }
83
84 if (!element || skip) {
85 cleanupExisting();
86 observedElementRef.current = null;
87 lastInViewRef.current = undefined;
88 return;
89 }
90
91 cleanupExisting();
92
93 observedElementRef.current = element;
94 let destroyed = false;
95
96 const destroyObserver = observe(
97 element,
98 (inView, entry) => {
99 const previousInView = lastInViewRef.current;
100 lastInViewRef.current = inView;
101
102 // Ignore the very first `false` notification so consumers only hear about actual state changes.
103 if (previousInView === undefined && !inView) {

Callers 8

OnInViewChangedComponentFunction · 0.90
MergeRefsComponentFunction · 0.90
ElementTestComponentFunction · 0.90
UseOnInViewRenderFunction · 0.85

Calls 3

observeFunction · 0.90
cleanupExistingFunction · 0.85
stopObservingFunction · 0.85

Tested by 7

OnInViewChangedComponentFunction · 0.72
MergeRefsComponentFunction · 0.72
ElementTestComponentFunction · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…