Building a Pagination Component with ReactJS
Tags: react, javascript, beginners, tutorial
Published: 2023-02-01 17:41:57

## Table of contents 
  * [Introduction](#intro)
  * [Setup](#setup)
  * [Pagination Component](#pagination)
  * [Pagination Setup](#pageSetup)
    * [Component State](#componentState)
    * [Setting up functionality](#pageFunction)
  * [Page UI](#uiSetup)
  * [RenderComponent](#renderComp)
  * [Conclusion](#conclusion)


### Introduction <a name="intro" />

![Pagination](https://i.makeagif.com/media/1-19-2023/scKStH.gif)

In this guide, we will learn how to create a Pagination component to display data at a certain amount on each page. By the end of this guide, we will have a complete working pagination component. We will focus more on the Pagination component's functionality aspect and will not dive too deep into the styling. We will provide an online editor link to follow along. In today's world wide web, we see lots and lots of data displayed on the user's screen. Usually, we get this data from a database (API) where we, the developers, need to figure out a way to display that data correctly; in some cases, we will have a designer with a design ready for us to work with, which only leaves us to worry about the functionality. With the tools you'll earn in this guide, you'll be able to take this component to the next level. 

* [Sandbox](https://codesandbox.io/s/pagination-reactjs-t96trc)

We will be working with data from a public API for Amiibos. If we want to learn more about the API we are working with, feel free to check out their [documentation](https://amiiboapi.com/).

> What we assume you know before starting this guide
* Basic JavaScript knowledge
* Basic ReactJS knowledge
* ReactJS hooks basic usage

_____

### Setup <a name="setup" />

Here is our setup project. Feel free to fork the project to start making changes.

`App.jsx` This is what our app will look like at the start.  


```js
import { useEffect, useState } from "react";
import axios from "axios";

export default function App() {
  // Our Data
  const [data, setData] = useState([]);

  // fetching our data
  useEffect(() => {
    axios
      .get("https://www.amiiboapi.com/api/amiibo")
      .then((res) => setData(res.data.amiibo))
      .catch((err) => console.log(err));
  }, []);

  return (
    <div>
      <h1 className=" text-2xl text-center">Pagination ReactJs</h1>
    </div>
  );
}
```

__What we need to know__

We import a few things at the start of our app. 

`useState` - allows us to manage the state of our application/component 

`useEffect` - allows us to make asynchronous calls within our component 

`Axios` - an HTTP framework that allows us to request data from the browser 

_____

### Creating Pagination Component <a name="pagination" />

__Problem__

We want to create our pagination component. We will create a file called `Pagination. jsx`
Create a functional component. Once created, render the `Pagination` component into our app.

__What we need to know__

Have an understanding of creating React functional components and exporting and importing.  

__Solution__

`Pagination.jsx` should have the following code.


```js
import React from "react";

export default function Pagination() {
  return (
    <div>
      <p> Pagination Component </p>
    </div>
  );
}
```


Import `Pagination.jsx` into `App.jsx` 

```js
import { useEffect, useState } from "react";
import axios from "axios";
import Pagination from "./Pagination";

export default function App() {
  // Our Data
  const [data, setData] = useState([]);

  // fetching our data
  useEffect(() => {
    axios
      .get("https://www.amiiboapi.com/api/amiibo")
      .then((res) => setData(res.data.amiibo))
      .catch((err) => console.log(err));
  }, []);

  return (
    <div>
      <h1 className=" text-2xl text-center">Pagination ReactJs</h1>

      <Pagination/>

    </div>
  );
}
```

_____

### Setting Up Pagination <a name="pageSetup" />

__Problem__

The pagination component will need to take in some data to work accordingly. We need to know how much data we want to display at once, how many pages we want to show the user to navigate through, a component or components that will render out with the data, and of course, the data itself we want to pass to our pagination. 

__What we need to know__

We need to understand how props are passed through functional components. Working with arguments will allow us to have more control over our data. 

Our `Pagination` component will take four parameters. We are naming our parameters to match our needs. 

`Pagination({data, RenderComponent, pageLimit, dataLimit})`

- `data`: the data we passing through
- `RenderComponent`: the component that will display our data
- `pageLimit`: the number of pages to select from
- `dataLimit`: the amount of data to display on each page

__Solution__

_Update_ `Pagination.jsx`

```js
export default function Pagination({data, RenderComponent, pageLimit,dataLimit}){

  return (
    <div>
      <p> Pagination Component </p>
    </div>
  );
}
```

_____

### Component State <a name="componentState" />

__Problem__

Our pagination will need to have a state of its own. We must determine how many total pages we obtain from our data. We need to track the current page we are viewing.  

__What we need to know__

The Math module can help us round up our total. We need to know the length of our data and divide that by the amount of data we want to display per page, giving us a total amount of pages.  

__Solution__

Starting at page one allows us to set a default value to our `currentPage` variable.

```js
const [pages] = useState(Math.round(data.length / dataLimit));
const [currentPage, setCurrentPage] = useState(1);
```

_Updated Code_

```js
import React, { useState } from "react";

export default function Pagination({data, RenderComponent, pageLimit,dataLimit}){
  
  const [pages] = useState(Math.round(data.length / dataLimit));
  const [currentPage, setCurrentPage] = useState(1);

  return (
    <div>
      <p> Pagination Component </p>
    </div>
  );
}
```

_Update_ `App.jsx`


`<Pagination data={data} pageLimit={5} dataLimit={10} RenderComponent={Amiibo} />
`

```js
import { useEffect, useState } from "react";
import axios from "axios";
import Amiibo from "./Amiibo";
import Pagination from "./Pagination";

export default function App() {
  // Our Data
  const [data, setData] = useState([]);

  // fetching our data
  useEffect(() => {
    axios
      .get("https://www.amiiboapi.com/api/amiibo")
      .then((res) => setData(res.data.amiibo))
      .catch((err) => console.log(err));
  }, []);

  return (
    <div>
      <h1 className=" text-2xl text-center">Pagination ReactJs</h1>

      <Pagination
        data={data}
        pageLimit={5}
        dataLimit={10}
      />
    </div>
  );
}

```

> If we forget what our arguments mean, check back to the pagination setup for a reminder. 

_____

### Setting Up Functionality <a name="pageFunction" />

__Problem__

Our pagination component needs to accomplish a few functionalities, such as going to the next page, going back to the previous page, changing to the selected page, and gathering data for the page. 

__What we need to know__

Have an idea of how to work with functions for our functional components and how to set a new state to our variable.

__Solution__

Here are the functions we will be working with 

```js
  function goToNextPage() {}

  function goToPreviousPage() {}

  function changePage() {}

  const getPaginatedData = () => {}

  const getPaginationGroup = () => {}
```

`goToNextPage` function

__Problem__

We need to figure out how we can go to the next page. What are some ways we can tell our component to change page values?

__What we need to know__

What is our current page

__Solution__

```js
function goToNextPage(){
  setCurrentPage((currentPage) => currentPage+ 1);
}
```

`goToPreviousPage` function

__Problem__

How can we go to the previous page? What are some ways we can tell our component to change page values?

__What we need to know__

What is our current page

__Solution__

```
function goToPreviousPage() {
  setCurrentPage((currentPage) => currentPage - 1);
}
```

`changePage` function

__Problem__

How can we get the value of the user's click? 

__What we need to know__

We need to know how to work with event handlers. 

__Solution__

```js
function changePage(event) {
  const pageNumber = Number(event.target.textContent);
  setCurrentPage(pageNumber);
 }
```

`getPaginatedData` function

__Problem__

We need to get the starting and last index of the array items within the page we are viewing. 

__What we need to know__

We need to know how to work with arrays to acquire index numbers. 

__Solution__

```js
const getPaginatedData = () => {
  const startIndex = (currentPage * dataLimit) - dataLimit;
  const endIndex = startIndex + dataLimit;
  return data.slice(startIndex, endIndex);
};
```

`getPaginationGroup` function

__Problem__

We need to determine the total number of pages depending on two values. 

__What we need to know__

We need to know our page limit, array fill, and map methods.  

__Solution__ 


```js
const getPaginationGroup = () => {
    let start = Math.floor((currentPage - 1) / pageLimit) * pageLimit;
    return new Array(pageLimit).fill().map((_, idx) => start + idx + 1);
};
```
We are returning a new array if we pass the last index of our page nav number.
 
_____

### Pagination UI <a name="uiSetup" />

Now that we have created all the functionality needed for our component, we can move on to creating elements for our UI. Since this does not require too much critical thinking, we will provide styled elements. We will need three elements: the previous button, the next button, and the navbar of numbers to allow the users to change page numbers. Last is the component we want to render for our data. 

__Previous Button__

```js
 <button
  onClick={goToPreviousPage}
  className={`prev ${currentPage <= 1 ? 'hidden' : ''}`}>
  prev
</button>
```

__Next Button__

```js
<button
  onClick={goToNextPage}
  className={`next ${currentPage >= pages ? 'hidden' : ''}`}>
  next
</button>
```

__Page Numbers__

```js
{getPaginationGroup().map((item, index) => (
  <button
  key={index}
  onClick={changePage}
  className={` paginationItem ${currentPage === item ? ' px-3 py-2 bg-gray-500/30 rounded-full' : null}`}
            >
    <span>{item}</span>
  </button>
))}
```

__Rendering Component__

```js
<div className="sm:grid sm:grid-cols-2 sm:gap-4 lg:grid-cols-3">
  {getPaginatedData().map((d, idx) => (
    <RenderComponent key={idx} data={d} />
  ))}
</div>
```


_____

### RenderComponent UI <a name="renderComp" />

Now that our Pagination component is complete, we can finish it up by adding the child component we want to render within our pagination component. We have provided a fully styled component to make it easier for us towards the end of this guide. Feel free to style it up how ever we would like.

`Amiibo.jsx` Our amiibo card component is already styled up for us with Tailwind

```js
import React from "react";

export default function Amiibo({ data }) {
  const amiibo = data.map((el) => (
    <div className="mx-auto w-full md:mx-0 md:flex md:flex-col">
      <div
        className="my-10 bg-gray-500/30 shadow-xl border-2 border-black rounded-lg p-4  mx-auto transition ease-in-out hover:scale-110 duration-300 "
        key={data.tail}
      >
        <img
          src={el.image}
          alt={el.character}
          className="mx-auto w-auto drop-shadow-2xl  max-h-56"
        />
        <p className="text-center text-2xl font-jost underline">
          {el.character}
        </p>

       <table className="mx-auto text-sm w-full text-left">
         <thead>
           <tr className="">
             <th>Country</th>
             <th>Release Date</th>
             <th>Game</th>
           </tr>
         </thead>

         <tbody className="font-semibold">
          <tr>
            <td>United States</td>
            <td>{el.release.na}</td>
            <td>{el.amiiboSeries}</td>
          </tr>

          <tr>
            <td>Japan</td>
            <td>{el.release.jp}</td>
          </tr>

          <tr>
            <td>Europe</td>
            <td>{el.release.eu}</td>
          </tr>

          <tr>
            <td>Australia</td>
            <td>{el.release.eu}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
 ));

 return <div>{amiibo}</div>;
}

```

Next import our `Amiibo` component into our `App` component.

```
import Amiibo from './Amiibo.jsx'
```

Finally 

Update `<Pagination />` component within `App.jsx`

Add `<Pagination data={data} pageLimit={5} dataLimit={10} RenderComponent={Amiibo} />` 

###Conclusion <a name="conclusion" />

By the end of this article, we have learned how to create and understand how a pagination component works. It is essential to understand how our code works altogether. Not only does it help us develop as developers, but it can also help us use the tools we are working with more efficiently.
These articles are mostly intended for personal use in becoming a better programmer and writer and developing my programming skills. Please drop any feedback or corrections you believe should be made to help me and others. Thank you for your time and for sticking this far!


- [Twitter](https://twitter.com/CleverOscarDev)
- [LinkedIn](https://www.linkedin.com/in/clever-oscar/)
- [Github](https://github.com/CleverOscar)