
Overview
Infinite scroll is a pattern where new data is loaded automatically as the user scrolls. It’s used widely in apps like Facebook, Instagram, or YouTube to keep users engaged without forcing them to click “Next Page.”
In this blog, we’ll build an infinite scroll product list using:
- React
- react-infinite-scroll-component
- A real dummy API (https://dummyjson.com/products)
Why Do We Need Infinite Scroll?
Traditional pagination splits content across multiple pages. This breaks the user’s flow, forces clicks, and reloads views unnecessarily.
Infinite scroll solves this by loading more content as the user moves down the page. It improves the experience in several ways:
Benefits:
- Fewer clicks: Content loads automatically—no need to press “Next.”
- Continuous browsing: Keeps the user in the same context without jumps.
- Better performance: Only a few items load at a time.
- Higher engagement: Smooth scrolling keeps users interested longer
When to Use It:
- Product catalogs: E-commerce sites showing large product lists.
- Blog feeds: News, articles, or updates where content keeps updating.
- Social feeds: Posts, comments, and replies that load continuously.
- Chat interfaces: Load previous messages on scroll up.
- Notification panels: Show recent activity without a full reload.
When to Avoid It:
- When SEO matters (content loaded on scroll isn’t always crawlable).
- When users need to bookmark or share exact pages.
- When the dataset is too large and unbounded scroll affects memory.
Infinite scroll is a great choice when your content is dynamic, long, and user-focused. Just make sure it fits the use case.
Setup
Step 1: Create a React App (if you don’t have one)
Use Vite for a fast setup:
npm create vite@latest infinite-scroll-app -- --template react
cd infinite-scroll-app
npm install
Step 2: Install Required Packages
You need two libraries: react-infinite-scroll-component for handling scroll detection and triggering loads & axios for making HTTP requests.
npm install react-infinite-scroll-component axios
Step 3: Set Up Your Component
Create a new file, e.g., ProductList.jsx or Products.js. This component will fetch and display data using infinite scroll logic.
You’re now ready to implement the real-time infinite scroll example using the DummyJSON API.
Real-Time Example:
Here’s a real working example using the DummyJSON products API.
import React, { useEffect, useState } from 'react';
import InfiniteScroll from 'react-infinite-scroll-component';
import axios from 'axios';
const ProductList = () => {
const LIMIT = 10;
const [products, setProducts] = useState([]);
const [hasMore, setHasMore] = useState(true);
const [skip, setSkip] = useState(0);
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async () => {
try {
const res = await axios.get(`https://dummyjson.com/products?limit=${LIMIT}&skip=${skip}`);
const newProducts = res.data.products;
setProducts(prev => [...prev, ...newProducts]);
setSkip(prev => prev + LIMIT);
if (products.length + newProducts.length >= res.data.total) {
setHasMore(false);
}
} catch (err) {
console.error('Error fetching products:', err);
}
};
return (
<div className="p-4 max-w-3xl mx-auto">
<h1 className="text-xl font-bold mb-4">Product List</h1>
<InfiniteScroll
dataLength={products.length}
next={fetchProducts}
hasMore={hasMore}
loader={<p className="text-center">Loading more products...</p>}
endMessage={<p className="text-center text-gray-500">You've reached the end.</p>}
>
{products.map((product) => (
<div key={product.id} className="border p-4 mb-3 rounded shadow-sm">
<h2 className="font-semibold">{product.title}</h2>
<p className="text-sm text-gray-700">{product.description}</p>
<p className="text-green-600 font-medium">${product.price}</p>
</div>
))}
</InfiniteScroll>
</div>
);
};
export default ProductList;
Explanation
Let’s break down how the infinite scroll works in this project.
1. useState and useEffect
These React hooks help manage the core data and behavior:
- products: an array that holds the list of products fetched so far. It grows with each scroll load.
- hasMore: a boolean that tells the scroll component whether more data is available. If false, it stops calling fetchProducts.
- skip: tracks how many items have been loaded already. This is used to calculate the next API call’s offset.
We call fetchProducts() initially inside useEffect so the first batch of data loads on page load.
2. fetchProducts() Function:
This function does all the work of fetching and updating data.
It sends a GET request to the DummyJSON API with limit and skip values:
https://dummyjson.com/products?limit=10&skip=0
After getting the response, it:
- Appends the new products to the existing list using setProducts.
- Increases the skip count for the next request.
- Checks if the total loaded items equal or exceed the total available. If yes, it sets hasMore to false.
This keeps the loading logic clean and repeatable.
3. <InfiniteScroll /> Component
This comes from the react-infinite-scroll-component package. It wraps the product list and handles:
- Detecting when the user has scrolled near the bottom
- Automatically calling next={fetchProducts}
- Displaying a loading message (loader) while data is loading
- Showing an end message when there’s nothing more to load
You don’t have to manually attach scroll event listeners or calculate positions—it’s all abstracted for you.
Conclusion
Infinite scroll is useful when you want a seamless data loading experience. With react-infinite-scroll-component, it takes just a few lines of code.
This approach works well for e-commerce, social feeds, or any content-heavy UI.
To recap:
- Use it when the user expects continuous content
- Always test performance and accessibility
- Stop loading when all data is fetched