paint-brush
How to Build a Simple and User-Friendly Infinite Scroll in Reactby@timmy471

How to Build a Simple and User-Friendly Infinite Scroll in React

by TimmyNovember 7th, 2024
Read on Terminal Reader
tldt arrow

Too Long; Didn't Read

This guide walks you through building an infinite scroll feature in React to load GitHub user data continuously, without traditional pagination
featured image - How to Build a Simple and User-Friendly Infinite Scroll in React
Timmy HackerNoon profile picture


Have you ever wondered how social media apps like Instagram manage to keep us scrolling, almost as if the content is endless? I know I have! It goes beyond just great content — it taps into a continuous flow that keeps us hooked, waiting for what’s next. Unlike traditional pagination, where users have to click "Next" to load more, infinite scrolling creates a seamless experience. Just as we reach the end of the visible content, new items load in, sparking curiosity and anticipation. This is the magic of infinite scroll: keeping the journey going without any interruptions.

Let’s dive right into it

In this guide, we’ll create a simple React app that uses infinite scroll to display GitHub users information. We'll be using:

  • React: For creating and managing the component-based structure of our app.
  • react-infinite-scroll-component: A popular package to manage the infinite scroll behavior.
  • Tailwind CSS: For quick and clean styling.
  • Axios: For making HTTP requests to the GitHub API.


1.) Set Up the Project

npx create-react-app infinite-scroll-app
cd infinite-scroll-app
npm start


Install axios, react-infinite-scroll-component and tailwindcss

npm install axios react-infinite-scroll-component tailwindcss


2.) Generate a Github Personal Token

Since we’ll be using the Github Apis, it’s important to get Access Token from GitHub To avoid rate limitations, Here’s how to create a GitHub Personal Access Token and use it in your project:

  • Go to your GitHub Settings.
  • Click on "Generate new token".
  • Select the scopes you need (for read-only public data, you typically just need the public_repo scope).
  • Generate and copy the token somewhere secure; you’ll need it in your app
  • Create an .env file in the root directory, include the github API url and the Access Token you just copied


REACT_APP_API_URL=https://api.github.com
REACT_APP_API_KEY=your_access_token



3.) Fetch the data from the Github Api

  const fetchUsers = async () => {
    try {
      const response = await axios.get(`${apiUrl}/users`, {
        headers: {
          Authorization: `Bearer ${apiKey}`,
        },
        params: {
          per_page: 20, // Adjust the number of users per page
          since: lastUserId, //The user id it should begin listing
        },
      });
      const newUsers = response.data;
      setUsers((prevUsers) => [...prevUsers, ...newUsers]);
      setLastUserId(newUsers[newUsers.length - 1]?.id); // update the last user ID
      setHasMore(newUsers.length > 0);
    } catch (error) {
      console.error("Error fetching users from GitHub API:", error);
      return [];
    }
  };

It’s important to note that Github uses since and not page just as is in the code above


4.) Setting Up The Infinite Scroll

       <InfiniteScroll
          dataLength={users.length}
          next={fetchUsers}
          hasMore={hasMore}
          loader={
            <h4 className="font-semibold mt-4 text-center">Loading...</h4>
          }
          endMessage={<p>No more users to display</p>}
        >
          <div className="flex flex-wrap gap-4 justify-between items-center">
            {users.map((user, key) => (
              <div
                key={key}
                className="border h-[8rem] w-[45%] sm:w-[30%] md:w-[20%] flex flex-col gap-2 items-center p-2"
              >
                <img
                  src={user.avatar_url}
                  alt={`Avatar image of ${user.login}`}
                  width="80px"
                  height="80px"
                  className="rounded-full"
                />
                <p>{user.login}</p>
              </div>
            ))}
          </div>
        </InfiniteScroll>


5. )Putting it all together

import axios from "axios";
import React, { useEffect, useState } from "react";
import InfiniteScroll from "react-infinite-scroll-component";

function App() {
  const [users, setUsers] = useState([]);
  const [lastUserId, setLastUserId] = useState(null);
  const [hasMore, setHasMore] = useState(true);

  const apiKey = process.env.REACT_APP_API_KEY;
  const apiUrl = process.env.REACT_APP_API_URL;

  const fetchUsers = async () => {
    try {
      const response = await axios.get(`${apiUrl}/users`, {
        headers: {
          Authorization: `Bearer ${apiKey}`,
        },
        params: {
          per_page: 20, // Adjust the number of users per page
          since: lastUserId, //The user id it should begin listing
        },
      });
      const newUsers = response.data;
      setUsers((prevUsers) => [...prevUsers, ...newUsers]);
      setLastUserId(newUsers[newUsers.length - 1]?.id); // update the last user ID
      setHasMore(newUsers.length > 0);
    } catch (error) {
      console.error("Error fetching users from GitHub API:", error);
      return [];
    }
  };

  useEffect(() => {
    fetchUsers();
  }, []);

  return (
    <div className="container py-8">
      <div className="mx-auto">
        <h1 className="text-4xl font-bold text-center mb-8">
          React Infinite Scroll Demo
        </h1>
        <InfiniteScroll
          dataLength={users.length}
          next={fetchUsers}
          hasMore={hasMore}
          loader={
            <h4 className="font-semibold mt-4 text-center">Loading...</h4>
          }
          endMessage={<p>No more users to display</p>}
        >
          <div className="flex flex-wrap gap-4 justify-between items-center">
            {users.map((user, key) => (
              <div
                key={key}
                className="border h-[8rem] w-[45%] sm:w-[30%] md:w-[20%] flex flex-col gap-2 items-center p-2"
              >
                <img
                  src={user.avatar_url}
                  alt={`Avatar image of ${user.login}`}
                  width="80px"
                  height="80px"
                  className="rounded-full"
                />
                <p>{user.login}</p>
              </div>
            ))}
          </div>
        </InfiniteScroll>
      </div>
    </div>
  );
}

export default App;


Conclusion

Infinite scrolling is a way to keep users engaged by continuously loading new content without interruption, and by now, you’ve experienced how easy it is to add to a React app. Using react-infinite-scroll-component, axios for API calls, and tailwindcss for styling, we’ve created a user-friendly experience that mimics popular social platforms.


Find the source code on github.

Check the app here.