🚀 Mastering Infinite Scrolling with React and Intersection Observer API 🔄
Pratham Srivastava
Posted on December 23, 2023
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);
-
callback
: Function triggered on intersection changes, receiving an array ofIntersectionObserverEntry
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,
}
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'));
Now you have a dazzling infinite scrolling product grid that dynamically loads more items as you scroll. Happy coding! 🚀🎨
Posted on December 23, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024