javascript / expert
Snippet
Custom Hook: useIntersectionObserver with Ref Stability and Callback Refs
Using a state-based callback ref ([setNode]) instead of a standard useRef ensures the IntersectionObserver correctly re-attaches if the element is conditionally rendered. This pattern is essential for performant lazy-loading and infinite scroll in React.
snippet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { useState, useEffect, useRef } from 'react';export function useIntersectionObserver(options: IntersectionObserverInit) {const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);const [node, setNode] = useState<Element | null>(null);const observer = useRef<IntersectionObserver | null>(null);useEffect(() => {if (observer.current) observer.current.disconnect();observer.current = new IntersectionObserver(([e]) => setEntry(e), options);if (node) observer.current.observe(node);return () => observer.current?.disconnect();}, [node, options]);return [setNode, entry] as const;}
nextjs
Breakdown
1
const [node, setNode] = useState
Using a state-based callback ref to ensure the observer re-binds when the DOM element changes.
2
observer.current.disconnect()
Crucial cleanup to prevent memory leaks and redundant observations when dependencies change.