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! πŸš€πŸŽ¨

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

Best practices for optimal infrastructure performance with Magento

Running a Magento store? Struggling with performance bottlenecks? Join us and get actionable insights and real-world strategies to keep your store fast and reliable.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❀️