React Intersection Observer

10.0.3 · active · verified Tue Apr 21

react-intersection-observer is a comprehensive React library that provides hooks and components for efficiently leveraging the browser's Intersection Observer API. It allows developers to monitor when a React component enters or leaves the viewport, enabling features like lazy loading images, implementing infinite scrolling, or triggering animations based on visibility. The current stable version is `10.0.3`, and the project maintains an active release cadence, frequently pushing updates and bug fixes. Key differentiators include its dual API (hooks like `useInView` and `useOnInView`, plus a `<InView>` component), optimized performance through observer instance reuse, native API alignment, robust TypeScript support, and a tiny bundle size (around ~1.15kB for `useInView`). The `useOnInView` hook, introduced in v10, offers a no-re-render alternative for side-effect-heavy workloads like analytics tracking, further enhancing its utility. It also includes comprehensive test utilities for Jest and Vitest.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to use the `useInView` hook to lazy load an image. The image only renders once it enters the viewport, using `triggerOnce` and a `threshold` of 0.1.

import React from 'react';
import { useInView } from 'react-intersection-observer';

const LazyLoadedImage = ({ src, alt }) => {
  const { ref, inView } = useInView({
    triggerOnce: true, // Only trigger once when it enters the viewport
    threshold: 0.1,    // Trigger when 10% of the element is visible
  });

  return (
    <div ref={ref} style={{ height: '300px', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#f0f0f0' }}>
      {inView ? (
        <img src={src} alt={alt} style={{ maxWidth: '100%', maxHeight: '100%' }} />
      ) : (
        <p style={{ color: '#888' }}>Loading image...</p>
      )}
    </div>
  );
};

const App = () => {
  return (
    <div>
      <div style={{ height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <h1>Scroll Down to See Image</h1>
      </div>
      <LazyLoadedImage src="https://via.placeholder.com/600x300.png?text=Intersection+Observer" alt="Placeholder Image" />
      <div style={{ height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <h2>End of Page</h2>
      </div>
    </div>
  );
};

export default App;

view raw JSON →