project image

Create infinite scroll functionality in React 

Overview

Infinite scrolling progressively loads more content as the user scrolls down the page. This creates a smooth and continuous experience, keeping users engaged without the interruption of page reloads.

In the dynamic world of web development, user experience is paramount. One way to enhance this experience is by implementing infinite scrolling, a feature that allows users to seamlessly load more content as they scroll down the page. In this blog post, we'll dive into creating the infinite scroll functionality in a React application, unlocking a world of possibilities for a smoother and more engaging user interface.

 

Understanding Infinite Scroll

 

Before we jump into the code, let's understand the concept of infinite scrolling. Instead of loading an entire page's worth of content at once, infinite scrolling progressively loads more content as the user scrolls down the page. This creates a smooth and continuous experience, keeping users engaged without the interruption of page reloads.

 

Setting Up the Project

 

Let's start by setting up a new React project with Typescript. Open your terminal and run the following commands:


npx create-react-app infinite-scroll-demo --template typescript
cd infinite-scroll-demo

This will create a new React project with Typescript support.

 

Create useInfiniteScroll Hook  
 

Create a hook that will check scroll behaviour and load the data accordingly. For simplicity, let's call it useInfiniteScroll.

// useInfiniteScroll.ts

import React from "react";

export interface useInfiniteScrollProps {
  ref?: React.RefObject<any>;
  option?: Omit<IntersectionObserverInit, "root">;
  onScrollEnd?: () => Promise<void> | void;
}

export const useInfiniteScroll = ({
  ref,
  onScrollEnd,
  option = {}
}: useInfiniteScrollProps) => {
  const isCalled = React.useRef<IntersectionObserverEntry | null>(null);
  const observer = React.useRef<IntersectionObserver | null>(null);
  React.useEffect(() => {
    observer.current = new IntersectionObserver(
      (entries, observer) => {
        if (
          entries[0].isIntersecting &&
          !isCalled.current?.target.isSameNode(entries[0].target)
        ) {
          isCalled.current = entries[0];
          void onScrollEnd?.();
          observer.unobserve(entries[0].target);
          observer.observe(ref?.current.lastChild as Element);
        }
      },
      {
        root: ref?.current,
        ...option
      }
    );
    if (ref?.current) {
      observer.current?.observe(ref?.current.lastChild as Element);
    }
  }, [onScrollEnd, option, ref]);
  return observer.current?.disconnect;
};

In this hook, we are accepting three parameters,

  • ref — reference of your container to determine the area of scrolling.
  • onScrollEnd — an event that will fire when you reach the end of scrolling.
  • option — will accept the configuration of the Intersection observer.

 

Create InfiniteScroll component

 

let's use this useInfiniteScroll hook and create a InfiniteScroll component.

// InfiniteScroll.tsx

import React, { useEffect } from "react";
import { useInfiniteScroll } from "./useInfiniteScroll";

export function InfiniteScroll() {
  const ref = React.useRef<HTMLDivElement>(null);
  const [isLoading, setIsLoading] = React.useState(false);
  const [products, setProducts] = React.useState([
    "gpjaznf",
    "hefztsugpwcdbxanvm",
    "kodhqlctubmvnigxasjwrpfzey",
    "utkigpjnlrymdqabvoexs",
    "cblkexdqy",
    "kdfzelrpnvctuyhmxb",
    "dybkzlefotpvwxmshacq",
    "dpmhcobxrqsgwfkvenlaiytjz",
    "hnerbpyxlagiocsmkqdvwf",
    "falqhvpbxykemjcsdtuzrogwni",
    "wunj",
    "sxdwmcobfr",
    "edcqmhyguwslkpnbrtvxajifoz",
    "gmkh",
    "cwxfilgjyku",
    "myjdcqziostvplfuwh",
    "cbptdeofihn",
    "hg",
    "mabxrozvlncpdjqesutfg",
    "huakjpmieo"
  ]);
  const unsubscribe = useInfiniteScroll({
    ref,
    async onScrollEnd() {
      setIsLoading(true);
      await setTimeout(() => {
        setIsLoading(false);
        setProducts((prev) => [
          ...prev,
          ...[...Array(20)].map(() => {
            const randomStr = "abcdefghijklmnopqrstuvwxyz"
              .split("")
              .sort(() => 0.5 - Math.random())
              .join("");
            return randomStr.slice(0, Math.random() * 26 + 2);
          })
        ]);
      }, 3000);
    },
    option: {
      threshold: 1
    }
  });
  useEffect(() => {
    return () => {
      if (unsubscribe) {
        unsubscribe();
      }
    };
  }, [unsubscribe]);
  return (
     <div
       className="scroll_container"
       ref={ref}
     >
       {products.map((el, id) => (
         <p key={id}>{el}</p>
       ))}
       {isLoading && <h5>Loading....</h5>} 
     </div>
  );
};

 

Adding in DOM tree

 

Let's add our component to our src/App.ts file.

// src/App.tsx

import React from "react";
import { InfiniteScroll } from "./InfiniteScroll"
import "./styles.css"; 

export default function App() { 
return ( 
	<div className="App"> 
		<h3>Infinity scroll</h3>
		<InfiniteScroll/>
	</div> 
	); 
};

 

Styling

 

Let's add some basic styling to make our component visually appealing.

/* styles.css */

.App {
  font-family: sans-serif;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
.scroll_container {
  height: 400px;
  width: 100%;
  background-color: beige;
  overflow: scroll;
}

Feel free to style your components, add loading spinners, or customize the UI based on your project requirements. The provided code is a foundation that you can build upon to create a seamless infinite scrolling experience in your React application.

 

infinite-scroll.gif

 

 

Conclusion

 

Implementing infinite scroll in a React application adds a touch of sophistication and user-friendliness, transforming the way users interact with your content. By breaking free from the constraints of traditional pagination, you can provide a more engaging and fluid experience, ultimately enhancing the overall user satisfaction. Experiment with the code, explore additional features, and let your creativity flourish as you create infinite possibilities for your React applications. Happy coding!