How to Implement Infinite Scrolling in React by Making a Custom Hook

Share your love

We often find ourselves in a situation where we have to deal with large sums of data in our Applications for user experience. If we render the data, in the same way, using the map function, the DOM Tree and the efficiency of our app will suffer the consequences like effects on speed and loading time, etc.

There are four solutions to this problem, and infinite scrolling in React is one of them. Infinite scrolling has become a popular feature in modern web applications, allowing users to seamlessly scroll through a large amount of content without clicking through multiple pages. 

In this blog post, we will not only learn how to implement infinite scroll in React using a custom hook so that we can apply it in any application but also the different ways using which we can implement it in our React App. 

Index

What is an infinite scroll?

Infinite scrolling is a web design technique that uses lazy loading to load only the content that is currently visible to the user, and as the user scrolls down, it loads more content automatically unlike the pagination component in which we have to click on a button to do so.

It creates a seamless browsing experience for the user and can help keep them engaged on the site for extended periods. React Infinite scroll component is often used in social media platforms, online marketplaces, and other types of websites where there is a large amount of content to be displayed.

Different Ways of Implementing Infinite Scroll in React

There are several methods using which we can make the infinite scrolling component in our app. They are – 

  1. Using hooks
  2. Using npm package
  3. Using Intersection Observer API

Using Hooks

We can create an Infinite scroll component in React without a plugin simply by using hooks. We can achieve this just by setting up a scroll event listener and using the useState and useEffect hooks to manage the loading of additional content. There are multiple ways of doing that. 

We will use this method in the blog to make our infinite scroll functional component. For this, we will be making a custom hook – the useInfiniteScroll hook that controls the display of items and how to load more content when the user scrolls to the bottom of the page.

We can also implement infinite scroll using React Query. React Query provides a hook called useInfiniteQuery that can be used to implement infinite scrolling. This hook is similar to the useQuery hook but with some differences that make it suitable for implementing infinite scrolling.

Using npm package

There are several npm packages available that can help us to implement infinite scroll in our App using React hooks. Some popular options include react-infinite-scroll-hook. You can install these packages using npm by running the command 

npm install react-infinite-scroll-hook

In the terminal. 

Using Intersection Observer API

According to the MDN docs, the Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport. It is mainly used for the Lazy-loading of images, making an infinite scroll, tracking the visibility of ad slots, and analytics data collection.

Just like hooks, we will use the Intersection observer API to load more data as the user reaches the end of the page. It will do this by observing whether the last element of the page is visible to the user or not. If it is visible, it will load more content else it will not

Now that we know what and how are we making that in this blog, let’s begin.

Creating the React App

First and foremost we have to create our React app. It’s straightforward to create a React app — just go to your working directory in your preferred IDE and enter the following command in the terminal:

npx create-react-app infinite-scrolling-in-react

If you are unsure how to set up a create-react-app project properly, you can refer to the official guide here at create-react-app-dev.‌‌

After the setup, run npm start in the same terminal to start localhost:3000 where our React app will be hosted. We can also see all our changes there.

We will be using Bootstrap for default styling and the rest will be done by custom CSS which will not be discussed in this blog as the main focus of this blog is explaining the construction and use of the different components that we have made in this app like a custom hook for implementing infinite scroll. But for people who want to practice the styling part as well, here is the GitHub repo of this project and the live link.

Understanding the UI of the App

Our app contains a number of cards containing a dummy image, name, and description generated from a test API and displayed in the form of cards as shown.

How to Implement Infinite Scrolling in React

Getting Data from the API

As told, we will be fetching data from the API using the try-and-catch method along with the fetch method. This whole process will be done under the useEffect hook of React and will be called at the top level of our app as per the rules of hooks provided to us by the React developer team. The code is as follows – 

useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://api.escuelajs.co/api/v1/products?offset=0&limit=20`
        );
        const json = await response.json();
        setData((pre) => [...pre, ...json]);
      } catch (error) {
        console.log(error);
      }
    };
    fetchData();
  }, []);

In the above code, there are two parameters in the API endpoint – offset and limit, the offset state is used to determine the starting index of the products to be fetched, and the limit is the limit of the number of products to be fetched – in this case, it is 20.

Creating the Custom Hook  – React Infinite Scroll Hook

We can then create a custom hook that will be responsible for getting and loading more posts.

To learn more about why and how to make a custom hook click here

Under the source folder, create a new folder hook and under it create a new file named useInfiniteScroll.js. Inside this function create a functional component as we can only use hooks inside the functional component, and move the useEffect hook with the fetchData() function there to make it a reusable Infinite scroll react functional component.

We will also be initializing a state using the useState hook – data, as an array to store all these values so that we can send them to our main component and display them in the card format. 

import { useEffect, useState } from "react";


const Loader = () => {
  const [data, setData] = useState([]);


  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://api.escuelajs.co/api/v1/products?offset=0&limit=20`
        );
        const json = await response.json();
        setData((pre) => [...pre, ...json]);
      } catch (error) {
        console.log(error);
      }
    };
    fetchData();


  return data;
};


export default Loader;

Working on the UI of the main component

As told, the UI of our App consists of many cards, and each card consists of random data, like a photo, a name, and a description, and all these values have already been fetched from the API and stored in the data state which we will be using in the main component to display the data using the map method.

import React from "react";
import Loader from "./hooks/useInfiniteScroll";


function App() {
  const data = Loader();


  return (
    <div className="container-fluid">
      <div className="row text-center mt-5">
        {data &&
          data.length > 0 &&
          data.map((item) => {
            return (
              <div key={item.id} className="col-md-4 col-sm-6 my-2">
                <img
                  src={item.images[0]}
                  alt={item.title}
                  className="card-img"
                />
                <h2>{item.title}</h2>
                <p>{item.description}</p>
              </div>
            );
          })}
      </div>
    </div>
  );
}


export default App;
React infinite scroll hook

Detecting the Bottom of the Page

Great, now that we have our basic layout of the app, it is time to work on the infinite scroll function of our app. An infinite scroll is triggered when the user hits the bottom of the page. For that functionality, we have to add an event listener to our custom hook.

For that first, we have to add an on-scroll event listener to the Window object to call a function called handleScroll() every time the window scrolls inside the custom hook that we have made.

const handleScroll = (e) => {
};
window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);


  return data;
};

Now with the help of the useEffect hook, we can give this function the same functionality as componentDidMount() and componentWillUpdate() lifecycle methods in React class components. 

useEffect(() => {
  const fetchData = async () => {
    try {
      const response = await fetch(
        `https://api.escuelajs.co/api/v1/products?offset=${offset}&limit=20`
      );
      const json = await response.json();
      setData((pre) => [...pre, ...json]);
    } catch (error) {
      console.log(error);
    }
  };
  fetchData();

  const handleScroll = (e) => {};
  window.addEventListener("scroll", handleScroll);
  return () => window.removeEventListener("scroll", handleScroll);
}, []);

As we know that there are three parameters when it comes to the useEffect() hook, and in the above code we have used the empty array [] parameter in the above code. Using the empty array parameter tells us that the useEffect() function will act as componentDidMount and will only when the component mounts.

Now that we have initialized a new state – offset with an initial value of 0. This state will be responsible for fetching more results from the API as the value of the offset changes.

The other thing that we have to do is check whether the Window object’s inner height plus the Document object’s scroll top is equal to the Document’s offset height. 

Now combining these two steps, our custom hook will look like this – 

import { useEffect, useState } from "react";


const Loader = () => {
  const [data, setData] = useState([]);
  const [offset, setOffset] = useState(0);


  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://api.escuelajs.co/api/v1/products?offset=${offset}&limit=5`
        );
        const json = await response.json();
        setData((pre) => [...pre, ...json]);
      } catch (error) {
        console.log(error);
      }
    };
    fetchData();


    const handleScroll = (e) => {
      const scrollHeight = e.target.documentElement.scrollHeight;
      const currentHeight =
        e.target.documentElement.scrollTop + window.innerHeight;
      if (currentHeight + 1 >= scrollHeight) {
        setOffset(offset + 5);
      }
    };
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, [offset]);


  return data;
};


export default Loader;

The final demo.

The Pros and Cons of Infinite Scroll

As the website is scrolled down, new content is continually downloaded, giving the impression of an infinite scroll. This technique can provide users with a seamless browsing experience. But the quote, “no one is perfect”, applies to infinite scroll as well. 

Pros of Infinite Scroll

Improved User EngagementInfinite scroll can keep users engaged by providing a continuous stream of content without requiring them to take any action to load more. This can result in longer session time and increased user engagement.

Reduced Wait TimesWith infinite scroll, content is loaded automatically as the user scrolls down the page. This can reduce wait times compared to traditional pagination, where users must click a button to load the next content page.

Better Mobile ExperienceInfinite scroll can provide a better browsing experience on mobile devices with limited screen space. Users can quickly scroll through content with their thumb without clicking small buttons to navigate between pages.

Cons of Infinite Scroll

Difficulty Finding Specific Content: With infinite scroll, it can be difficult for users to find specific content or return to a previous point on the page. The content continuously changes as the user scrolls down the page.

No Sense of Completion: With infinite scroll, users may not have a sense of completion because there is no clear end to the content. This can result in users feeling overwhelmed or unsatisfied with their browsing experience.

Increased Resource Usage: Infinite scroll can increase resource usage on both the client and server sides. As more content is loaded, more memory and processing power may be required to handle the additional data.

Tips for Debugging infinite scrolling in React

Here are some tips for debugging infinite scrolling in React:

Check the API response: Make sure that the API endpoint you use to fetch data for infinite scrolling returns the expected data. The API answer can be examined using Postman or the browser’s developer tools.

Check the scroll event: Make sure it is being triggered correctly and your code responds as expected. You can use `console.log` statements or breakpoints to debug the scroll event handler.

Check the state: Make sure your component’s state is updated correctly as new data is fetched. You can use React’s developer tools to inspect the state of your component.

Check for errors: Make sure that no errors are being thrown in your code or any third-party libraries you use. You can use the browser’s developer tools to check for errors in the console.

Simplify your code: If you are having trouble debugging your infinite scrolling implementation, try simplifying your code by removing any unnecessary features or complexity. This can make it easier to identify and fix issues.

Conclusion

In conclusion, infinite scroll is a design pattern where content is continuously loaded as the user scrolls down the page. This technique can provide users with a seamless browsing experience, but it has pros and cons. You can implement infinite scroll using React hooks or libraries like React Query. There are several npm packages available that can help you implement infinite scroll using React hooks. When implementing infinite scroll in React, it’s essential to consider the pros and cons carefully and follow best practices for debugging any issues.

Frequently Asked Questions

Is infinite scroll suitable for all types of content?

No, infinite scroll is not ideal for all types of content. It works best for long-form content like articles, social media feeds, or product catalogs.

How do I optimize infinite scroll performance in React?

To optimize infinite scroll performance in React, you can use server-side rendering, lazy loading, and pagination to reduce the amount of data loaded simultaneously and improve the user experience.

Can I implement infinite scroll using CSS?

No, infinite scroll cannot be implemented using CSS alone. You must use JavaScript to dynamically load new content as the user scrolls down the page.

How do I handle errors in the infinite scroll?

To handle errors in an infinite scroll, add an error handling code to your API fetch function and display an error message or retry button if the data fails to load.

How do you make Infinite Scrolling in React?

There are mainly two ways using which we can make an infinite scroll in React –

  1. Using an npm package -react-infinite-scroll-component.
  2. By building a custom infinite scroll component

What is the Difference between Lazy Loading and Infinite Scrolling?

Lazy loading is a technique in which content is loaded as the user scrolls down the page. This technique helps to improve the overall performance of the website by only loading content that is needed at that particular moment.

Infinite scrolling is a technique in which content is continuously loaded as the user scrolls down the page. This technique helps to provide a more seamless browsing experience as the user never has to click to get to the next page. It also allows for a more continuous interaction with the content as the user can keep scrolling and loading new content without interruption.

Share your love