Pagination in React
Tags: javascript, webdev, react
Published: 2022-06-10 18:10:40


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](#step-1)
2. [Writing code to fetch data](#step-2)
3. [Writing the Pagination Component](#step-3)
4. [Putting the whole code together](#step-4)

Let's get started!

### 1. Setting up files <a name="step-1"></a>
Create a react app by using the create react app template
```js
npx create-react-app pagination-app
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/72govg69m2c9zwohsxzy.png) 

### 2. Writing code to fetch data <a name="step-2"></a>

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

```js
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;
```

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](https://dev.to/shraddha1402/fetch-api-basics-6lo)

### 3. Writing the Pagination Component <a name="step-3"></a>
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.

```js
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 };

```

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.

```js
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>
```

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.

```css
.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;
}

```

### 4. Putting the whole code together <a name="step-4"></a>

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

```js
 <div className="App">
    <Pagination pageDataLimit={5} posts={posts} />
 </div>
```

Once you have written all the code, run

```js
npm start
```

The whole code and demo is uploaded on [github](https://github.com/shraddha-1402/Pagination-React).
Happy Coding!