useIntersectionObserver in React
From the React Custom Hooks cheat sheet · Interaction & Lifecycle Hooks · verified Jul 2026
useIntersectionObserver
Detect when an element enters the viewport - lazy load, infinite scroll
jsx
import { useEffect, useRef, useState } from 'react'
function useIntersectionObserver(options?: IntersectionObserverInit) {
const ref = useRef<HTMLElement>(null)
const [entry, setEntry] = useState<IntersectionObserverEntry>()
useEffect(() => {
const el = ref.current
if (!el) return
const io = new IntersectionObserver(([e]) => setEntry(e), options)
io.observe(el)
return () => io.disconnect()
}, [options?.root, options?.rootMargin, options?.threshold])
return { ref, entry, isIntersecting: !!entry?.isIntersecting }
}
// Usage
function LazyImage({ src, alt }: { src: string; alt: string }) {
const { ref, isIntersecting } = useIntersectionObserver({ rootMargin: '200px' })
return (
<div ref={ref as any}>
{isIntersecting ? <img src={src} alt={alt} /> : <div className="placeholder" />}
</div>
)
}💡 IntersectionObserver beats scroll listeners - browser-optimized, throttled by default
⚡ `rootMargin: "200px"` pre-fetches BEFORE the element is on screen
📌 freezeOnceVisible prevents re-triggering for one-shot animations
🎯 Sentinel + this hook is the cleanest infinite-scroll pattern in React
scrolllazy-loadperformance