DEV Community

Shraddha Gupta
Shraddha Gupta

Posted on • Edited on

Pagination in React

While designing any website we need to think about how should we display our data, such that our users can consume it properly and are not overwhelmed by it. The more organised the data, the better the website's user experience.

Pagination is one such method for achieving this. It is a method of dividing web content into discrete pages, thus presenting content in a limited and digestible manner.

In this blog we are going to make a simple react app where we will fetch data from this https://jsonplaceholder.typicode.com/posts API and display it in Pagination format.

Here we will be fetching all the data at once and then display it in pages, but with a backend you can fetch small chunks of data for each page, the frontend pagination code for both the methods will remain the same.

  1. Setting up files
  2. Writing code to fetch data
  3. Writing the Pagination Component
  4. Putting the whole code together

Let's get started!

1. Setting up files

Create a react app by using the create react app template

npx create-react-app pagination-app
Enter fullscreen mode Exit fullscreen mode

or you can also code on codesandbox or stackblitz

After the app is created, your folder structure might look like this
Folder structure of react app

2. Writing code to fetch data

We will use the fetch API to get the data from the jsonplaceholder API and store it in a state. Remove all the code from your App.js file and write the code given below

import { useState } from "react";

const URL = "https://jsonplaceholder.typicode.com/posts";

function App() {
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    fetch(URL)
      .then((response) => {
        if (response.ok) return response.json();
        throw new Error("could not fetch posts");
      })
      .then((posts) => setPosts(posts))
      .catch((error) => console.error(error));
  },[]);
  return <div className="App"></div>;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Here, we have written the fetch function inside useEffect hook and passed an empty dependency array, this will make sure that our fetch function runs only once, after the page is loaded. If the data is fetched successfully, it will be stored in the state, else the error will be displayed in the console.

If you wish to understand more about how fetch works, you can read my blog Fetch API: Basics

3. Writing the Pagination Component

Now, after getting the data, we will write our Pagination Component.

Create a file Pagination.js in your src folder.
We will display 5 posts per page, and that will be our page limit. We will store the current page number in a state and update it using the Previous and Next button, also we will display 3 consecutive page numbers, viz previous, current and next.

import React, { useState, useEffect } from "react";

const Pagination = ({ pageDataLimit, posts }) => {
  const [currPageNo, setCurrPageNo] = useState(1);
  const [currPagePosts, setCurrPagePosts] = useState([]);
  const [pageNumberGroup, setPageNumberGroup] = useState([]);

  useEffect(() => {
    setCurrPagePosts(getPageData());
    setPageNumberGroup(getPageNumberGroup());
    console.log("run");
  }, [posts, currPageNo]);

  const nextPage = () => setCurrPageNo((prev) => prev + 1);
  const previousPage = () => setCurrPageNo((prev) => prev - 1);
  const changePageTo = (pageNumber) => setCurrPageNo(pageNumber);
  const getPageData = () => {
    const startIndex = currPageNo * pageDataLimit - pageDataLimit;
    const endIndex = startIndex + pageDataLimit;
    return posts.slice(startIndex, endIndex);
  };
   const getPageNumberGroup = () => {
    let start = Math.floor((currPageNo - 1) / 3) * 3;
    console.log(new Array(3).fill(" ").map((_, index) => start + index + 1));
    return new Array(3).fill(" ").map((_, index) => start + index + 1);
  };
return (
    <div></div>
  );
};

export { Pagination };

Enter fullscreen mode Exit fullscreen mode

Here, our pagination component is getting posts and page limit as props. The getPageData funtion will be used to calculate the posts to be shown in each page. Using the start and end index we will slice the posts array and update the currPagePosts state.
The getPageNumberGroup function is used to display the previous, current and the next page numbers.

Now, we will map over the currPagePosts and pageNumberGroup states to display the posts.

return (
    <div>
      <h1 className="heading">Posts in Pagination</h1>
      <ul className="posts-container list-style-none">
        {currPagePosts.map(({ id, title, body }) => {
          return (
            <li key={id} className="post">
              <h3>{title}</h3>
              <p>{body}</p>
            </li>
          );
        })}
      </ul>
      <div className="page-num-container">
        <button
          className={`page-change-btn ${currPageNo === 1 ? "disabled" : ""}  `}
          disabled={currPageNo === 1}
          onClick={previousPage}
        >
          Previous
        </button>
        <ul className="page-num-container list-style-none">
          {pageNumberGroup.map((value, index) => {
            return (
              <li
                className={`page-number ${
                  currPageNo === value ? "active" : ""
                } `}
                key={index}
                onClick={() => changePageTo(value)}
              >
                {value}
              </li>
            );
          })}
        </ul>
        <button
          disabled={currPageNo === Math.floor(posts.length / pageDataLimit)}
          className={`page-change-btn ${
            currPageNo === Math.floor(posts.length / pageDataLimit)
              ? "disabled"
              : ""
          }  `}
          onClick={nextPage}
        >
          Next
        </button>
      </div>
    </div>
Enter fullscreen mode Exit fullscreen mode

We are first displaying all the posts, below that the page numbers along with the buttons. The previous button will be disabled when we are on the first page and similarly the next button will be disabled when we are at the last page.

Below are the styles for the pagination component. Write the code in App.css file and import it in Pagination.js file.

.heading {
  text-align: center;
  margin: 1rem;
}

.posts-container {
  display: grid;
  grid-template-columns: 18rem 18rem 18rem;
  gap: 1rem;
  align-items: stretch;
  justify-content: center;
}

.post {
  max-width: 16rem;
  text-align: center;
  padding: 1rem;
  margin: 0.5rem;
  color: "#c4c4c4";
  border: 1px solid purple;
  border-radius: 0.25rem;
}

.page-num-container {
  display: flex;
  align-items: center;
  justify-content: center;
}

.page-change-btn {
  padding: 0.5rem 1rem;
  margin: 0 0.5rem;
  border: none;
  border-radius: 0.25rem;
  outline: none;
  background-color: purple;
  color: white;
  cursor: pointer;
}

.disabled {
  cursor: not-allowed;
  background-color: gray;
}

.page-number {
  border: 1px solid grey;
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  line-height: 2rem;
  text-align: center;
  margin: 0 0.25rem;
  cursor: pointer;
}

.active {
  border-color: purple;
}

.list-style-none {
  list-style: none;
  padding-inline-start: 0;
}

Enter fullscreen mode Exit fullscreen mode

4. Putting the whole code together

We have our Pagination component ready, now we just need to call the component in App.js file.

 <div className="App">
    <Pagination pageDataLimit={5} posts={posts} />
 </div>
Enter fullscreen mode Exit fullscreen mode

Once you have written all the code, run

npm start
Enter fullscreen mode Exit fullscreen mode

The whole code and demo is uploaded on github.
Happy Coding!

Top comments (0)