Editor’s note: This article was last updated on 14 April 2023 to include information about the Intersection Observer API.
In today’s fast-paced digital landscape, providing a seamless and engaging user experience is more important than ever before. One popular method for improving user experience is implementing infinite scrolling, a web design technique that loads content continuously as the user scrolls down the page.
This intuitive feature eliminates the need for traditional pagination and has become a staple in modern web applications. In this article, we’ll explore three unique approaches to implementing infinite scrolling in React applications:
To follow along with this article, you’ll need a basic understanding of React. Let’s get started!
Jump ahead:
Throughout this article, we’ll build on a consistent foundation to implement the various infinite scrolling techniques. For each method, we’ll adapt the following steps and code snippets.
First, we’ll set up the initial state for our component. This includes the list of items to display, the necessary loading and error indicators, and a variable to keep track of the current page number:
import React, { useState, useEffect, useRef } from 'react'; const InfiniteScrollExample = () => { const [items, setItems] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [page, setPage] = useState(1); // ... rest of the component };
Next, we’ll create a function to fetch data from an API or another data source, increment the page number, and update the state with the fetched items. Additionally, we’ll handle any errors during the data fetching process:
const fetchData = async () => { setIsLoading(true); setError(null); try { const response = await fetch(`https://api.example.com/items?page=${page}`); const data = await response.json(); setItems(prevItems => [...prevItems, ...data]); setPage(prevPage => prevPage + 1); } catch (error) { setError(error); } finally { setIsLoading(false); } };
fetchData
on component mountLastly, we’ll use the useEffect
Hook to call the fetchData
function when the component mounts initially:
useEffect(() => { fetchData(); }, []);
These foundational steps will be present in all of the techniques we discuss in this article. As we explore each method for implementing infinite scrolling React, we’ll modify and expand upon this base.
Building the entire infinite scroll implementation from scratch involves handling the scroll event, loading more data, and updating the state in your React application. This approach provides you with full control over customization and functionality.
Extending our basic setup, we’ll first create a function to handle the scroll
event. This function will check if the user has reached the bottom of the page and call fetchData
if necessary. We’ll add a scroll
event listener to the window
object and remove it when the component is unmounted:
const handleScroll = () => { if (window.innerHeight + document.documentElement.scrollTop !== document.documentElement.offsetHeight || isLoading) { return; } fetchData(); }; useEffect(() => { window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, [isLoading]);
Finally, we render the items, the loading indicator, and any error messages within the component:
return ( <div> <ul> {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> {isLoading && <p>Loading...</p>} {error && <p>Error: {error.message}</p>} </div> );
With that, we have a fully functional infinite scroll implementation built from scratch. This approach allows for extensive customization and more control over functionality. However, it may be more time-consuming and require more maintenance than using an existing library or component.
Using an existing infinite scroll library or component can save you time and effort as you leverage pre-built, pre-tested solutions while retaining customization options. One popular library for implementing infinite scrolling in React is react-infinite-scroll-component
. Let’s learn how to use this library to create infinite scrolling in our React application.
First, install the react-infinite-scroll-component
library using npm or Yarn:
npm install react-infinite-scroll-component or yarn add react-infinite-scroll-component
Then, we’ll extend our basic setup, import the InfiniteScroll
component from the library, and wrap the list of items in it. Configure the component by passing the necessary props like dataLength
, next
, hasMore
, and loader
:
import InfiniteScroll from 'react-infinite-scroll-component'; // ... return ( <div> <InfiniteScroll dataLength={items.length} next={fetchData} hasMore={true} // Replace with a condition based on your data source loader={<p>Loading...</p>} endMessage={<p>No more data to load.</p>} > <ul> {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> </InfiniteScroll> {error && <p>Error: {error.message}</p>} </div> );
With that, we’ve implemented infinite scrolling in our React application using the react-infinite-scroll-component
library. We didn’t use scroll
handling because react-infinite-scroll-component
handles that for us.
The react-infinite-scroll-component
library offers a faster and more streamlined implementation process but still provides customization options, like for scroll height and scroll overflow. However, you should keep in mind the trade-off of introducing additional dependencies in your project.
The Intersection Observer API is a modern development technique that can detect when elements come into view, thereby triggering content loading for infinite scrolling. The Intersection Observer API observes changes in the intersection of target elements with an ancestor element or the viewport, making it well-suited for implementing infinite scrolling.
Extending our basic setup, create a ref
for the observer
target element and set up the Intersection Observer in a useEffect
Hook. When the target element comes into view, call the fetchData
function as follows:
const observerTarget = useRef(null); useEffect(() => { const observer = new IntersectionObserver( entries => { if (entries[0].isIntersecting) { fetchData(); } }, { threshold: 1 } ); if (observerTarget.current) { observer.observe(observerTarget.current); } return () => { if (observerTarget.current) { observer.unobserve(observerTarget.current); } }; }, [observerTarget]);
Then, render the items, loading indicator, error messages, and the observer
target element within the component:
return ( <div> <ul> {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> {isLoading && <p>Loading...</p>} {error && <p>Error: {error.message}</p>} <div ref={observerTarget}></div> </div> );
By leveraging the Intersection Observer API, we have created an efficient and performant infinite scrolling solution in our React application. This approach offers a modern, browser-native method for detecting when elements come into view, but it may not be supported in all browsers or environments without using a polyfill.
Infinite scrolling is a powerful web design technique. It enhances the user experience by progressively loading content as users scroll down a page, thereby eliminating the need for pagination.
In this article, we explored three different approaches for implementing infinite scrolling in React applications. Each technique has its own advantages and potential drawbacks, so it’s essential to choose the method that best suits your specific requirements and your users’ needs.
By implementing infinite scrolling in your React applications, you can provide an intuitive and engaging user experience that keeps visitors engaged with your content. I hope you enjoyed this article! Be sure to leave a comment if you have any questions.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowIn web development projects, developers typically create user interface elements with standard DOM elements. Sometimes, web developers need to create […]
Toast notifications are messages that appear on the screen to provide feedback to users. When users interact with the user […]
Deno’s features and built-in TypeScript support make it appealing for developers seeking a secure and streamlined development experience.
It can be difficult to choose between types and interfaces in TypeScript, but in this post, you’ll learn which to use in specific use cases.
2 Replies to "3 ways to implement infinite scroll in React"
Hi,
Thanks,
I followed you & implemented the infinite scroll. I have been facing this issue.
I have set page size 30, So for each API response I receive the 30 data. The problem is, when I open the application in big screen like TV/projector, Initial API call loads the 30 data & no scroll appear due to large screen. But I have 1000 data in Database.
I told team, We could increase the initial page size 100, then they asked suppose after increased size What If the scroll doesn’t appear on window. More over, they want to keep page size 30 only, do not want to change.
How to solve when I open the application in big screen, load the data until scroll appear?
This error occured because you did not specify the context in which the infinite scroll should work. It defaults to the viewport if not set.
The solution is that you pass in the root which is a selector to the options object as shown below.
let options = {
root: document.querySelector(“#scrollArea”),
rootMargin: “0px”,
threshold: 1.0,
};
let observer = new IntersectionObserver(callback, options);