React IntersectionObserver Hook
React useIntersectionObserver hook for element visibility detection. Track viewport intersections with configurable thresholds for Next.js apps.
Need help with lazy loading or infinite scroll?
Join our Discord community for help from other developers.
Ever tried to implement lazy loading or scroll animations and ended up wrestling with scroll event listeners and manual viewport calculations? You know the drill—measuring element positions, calculating visibility percentages, dealing with performance issues from constant scroll events. This free open source React useIntersectionObserver custom hook handles all that visibility detection complexity so you can focus on building smooth user experiences instead of reinventing intersection math in your React applications.
useIntersectionObserver showcase
Efficient element visibility tracking with native browser APIs:
This free open source React hook simplifies viewport intersection detection with TypeScript support for modern JavaScript applications. Whether you're building lazy loading systems, scroll animations, or analytics tracking in your Next.js projects, this React hook keeps your visibility logic performant.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-intersection-observer.json
npx shadcn@latest add https://www.shadcn.io/registry/use-intersection-observer.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-intersection-observer.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-intersection-observer.json
Why most visibility detection implementations suck
Look, you could keep writing scroll event handlers and calculating element positions manually. But then you hit the performance wall—scroll events fire constantly, getBoundingClientRect is expensive, and you need to throttle everything to keep things smooth.
Most developers use scroll listeners with getBoundingClientRect() calculations, causing performance bottlenecks in React applications. Or they forget to throttle scroll events, leading to janky animations and poor user experience. Some skip cleanup entirely and wonder why their scroll handlers accumulate over time in TypeScript components.
This React hook uses the native Intersection Observer API under the hood in Next.js projects, which is specifically designed for efficient visibility tracking. The browser handles all the optimization, so you get smooth performance without the complexity.
Plus it handles all the edge cases—cleanup on unmount, browser compatibility, threshold configurations, freeze-once-visible behavior. No more memory leaks or janky scroll performance in JavaScript applications.
This free open source React hook manages efficient visibility detection while you focus on building features. Whether you're creating React applications, Next.js dashboards, or TypeScript components, reliable intersection tracking keeps your JavaScript development performant.
Features
- Intersection Observer API with native browser support and automatic cleanup in React applications
- Configurable thresholds supporting single values or arrays for precise detection in TypeScript components
- Freeze on visible option to lock state once element becomes visible in Next.js projects
- Custom root elements allowing observation relative to any container in JavaScript development
- TypeScript support with complete type definitions and flexible destructuring for React frameworks
- Performance optimized using efficient native browser APIs with minimal overhead in modern applications
- Free open source designed for modern React development workflows
When you'll actually use this
Real talk—this isn't for every visibility check in React applications. Simple show/hide logic often works fine with CSS or basic state. But when you need performance-critical visibility detection or complex threshold logic, this React hook delivers in Next.js projects.
Perfect for:
- Lazy loading - Images, videos, and content that loads when visible built with TypeScript
- Scroll animations - Trigger effects when elements enter the viewport using React patterns
- Analytics tracking - Monitor content exposure and engagement metrics in JavaScript applications
- Infinite scroll - Detect when users reach the bottom of lists in React components
- Performance optimization - Defer expensive operations until needed in Next.js applications
- Progress indicators - Track reading progress and section visibility using TypeScript validation
API Reference
useIntersectionObserver
Option | Type | Default | Description |
---|---|---|---|
threshold | number | number[] | 0 | Visibility percentage needed to trigger (0-1) |
root | Element | Document | null | null | Container element for intersection calculation |
rootMargin | string | "0%" | Margin around root element for intersection area |
freezeOnceVisible | boolean | false | Lock intersection state once element becomes visible |
initialIsIntersecting | boolean | false | Initial intersection state before observation |
onChange | function | undefined | Callback fired when intersection state changes |
Return Value (Supports both tuple and object destructuring)
Property | Type | Description |
---|---|---|
ref | (node?: Element | null) => void | Ref callback to attach to target element |
isIntersecting | boolean | Current visibility state based on threshold |
entry | IntersectionObserverEntry | undefined | Raw intersection observer entry data |
Common gotchas
Ref attachment requirement: The React hook won't work until you assign the ref to an actual element in your render in TypeScript components. Make sure the element exists and has dimensions.
Modern browser API limitation: Intersection Observer is supported in all modern browsers but won't work in Internet Explorer in React applications. The hook handles graceful degradation for older browsers.
Threshold percentage meanings: 0 means any pixel visible, 1 means completely visible in Next.js projects. Arrays let you track multiple visibility levels for complex animations.
Freeze behavior permanence: Once freezeOnceVisible
is true and the element becomes visible, it stays visible even if scrolled away in JavaScript applications—perfect for one-time animations but can be confusing for debugging.
Root margin CSS syntax: rootMargin uses CSS margin syntax ("10px 20px") not JavaScript object syntax in React development. Incorrect syntax will cause unexpected behavior.
Observer instance sharing: Multiple elements with identical options share the same observer instance for performance in TypeScript projects, but different options create separate observers.
Related hooks you will also like
useEventListener
Custom event listener management for scroll and resize events
useWindowSize
Track window size changes for responsive intersection logic
useMediaQuery
Responsive design detection that complements visibility tracking
useBoolean
Boolean state management for intersection visibility states
useDebounceValue
Debounce rapid intersection changes for smoother animations
useScrollLock
Scroll management for modal and overlay intersection behavior
Questions you might have
React useHover Hook
React useHover hook for hover state detection. Track mouse interactions with precise event handling and TypeScript support for Next.js applications.
React useInterval Hook
React useInterval hook for setInterval management. Automatic cleanup and pause/resume functionality for timers with TypeScript support for Next.js apps.