DEV Community

Pratham Srivastava
Pratham Srivastava

Posted on

πŸš€ Mastering Infinite Scrolling with React and Intersection Observer API πŸ”„

Welcome to the world of dynamic web experiences! Today, we're diving into the Intersection Observer API, a powerful tool that brings life to features like lazy loading, infinite scrolling, and more. Let's explore the key concepts and build a stylish infinite scrolling product grid using React.

Key Concepts 🧠

1. Observer πŸ‘€

  • An IntersectionObserver watches target elements and triggers a callback on intersection changes.
  • Monitors one or more target elements for changes in their intersection status.

2. Target Element 🎯

  • The observed element, known as the "target element," is the one undergoing intersection monitoring.

3. Intersection Ratio πŸ“

  • Represents the ratio of the target element's intersection with the root (viewport).
  • 0 means no intersection, 1 means the entire element is within the viewport.

4. Thresholds 🎯

  • Configurable values (0 to 1) triggering the callback when the intersection ratio crosses them.

5. Root and Root Margin 🌐

  • root: Element for intersection checking (default is the browser's viewport).
  • rootMargin: Margin around the root or specified ancestor to adjust intersection triggering.

Basic Usage πŸ”§

const observer = new IntersectionObserver(callback, options);
observer.observe(targetElement);
Enter fullscreen mode Exit fullscreen mode
  • callback: Function triggered on intersection changes, receiving an array of IntersectionObserverEntry objects.
  • options: Configuration object for the observer.

IntersectionObserverEntry πŸ“Š

Object providing details about the intersection between the target element and the root.

{
  time: DOMHighResTimeStamp,
  target: Element,
  rootBounds: DOMRectReadOnly,
  boundingClientRect: DOMRectReadOnly,
  intersectionRect: DOMRectReadOnly,
  intersectionRatio: number,
  isIntersecting: boolean,
}
Enter fullscreen mode Exit fullscreen mode

Putting it into Action πŸš€

Let's create an infinite scrolling product grid with React and Intersection Observer. Check out the code below with some added emojis for extra flair! πŸŽ‰

// Your React Component
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';

const PRODUCTS_PER_LOAD = 10;

// Mock API for fetching products
const mockAPI = {
  fetchProducts: (start, limit) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(
          Array.from({ length: limit }).map((_, idx) => ({
            id: start + idx,
            name: `Product ${start + idx}`,
            image: 'https://via.placeholder.com/150',
          }))
        );
      }, 1000);
    });
  },
};

function InfiniteScrollProducts() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const loadMoreRef = useRef(null); 

  useEffect(() => {
    loadMoreProducts();

    const observer = new IntersectionObserver(
      (entries, observerInstance) => {
        if (entries[0].isIntersecting && !loading) {
          loadMoreProducts();
        }
      },
      { threshold: 1.0 }
    );

    // start observing the loadMore button
    if (loadMoreRef.current) {
      observer.observe(loadMoreRef.current);
    }

    return () => {
      if (loadMoreRef.current) {
        observer.unobserve(loadMoreRef.current);
      }
    };
  }, [products, loading]);

  const loadMoreProducts = async () => {
    setLoading(true);
    const newProducts = await mockAPI.fetchProducts(
      products.length,
      PRODUCTS_PER_LOAD
    );
    setProducts((prev) => [...prev, ...newProducts]);
    setLoading(false);
  };

  return (
    <div>
      <div className="products-grid">
        {products.map((product) => (
          <div key={product.id} className="product-card">
            <img src={product.image} alt={product.name} />
            <h3>{product.name}</h3>
          </div>
        ))}
      </div>
      {loading && <p ref={loadMoreRef}>Loading... πŸ”„</p>}
    </div>
  );
}

// Render the component
ReactDOM.render(<InfiniteScrollProducts />, document.getElementById('root'));
Enter fullscreen mode Exit fullscreen mode

Now you have a dazzling infinite scrolling product grid that dynamically loads more items as you scroll. Happy coding! πŸš€πŸŽ¨

Top comments (0)