Table of contents
Introduction
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.
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.
What we assume you know before starting this guide
- Basic JavaScript knowledge
- Basic ReactJS knowledge
- ReactJS hooks basic usage
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.
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
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.
import React from "react";
export default function Pagination() {
return (
<div>
<p> Pagination Component </p>
</div>
);
}
Import Pagination.jsx
into App.jsx
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
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
export default function Pagination({data, RenderComponent, pageLimit,dataLimit}){
return (
<div>
<p> Pagination Component </p>
</div>
);
}
Component State
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.
const [pages] = useState(Math.round(data.length / dataLimit));
const [currentPage, setCurrentPage] = useState(1);
Updated Code
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} />
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
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
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
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
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
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
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
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
<button
onClick={goToPreviousPage}
className={`prev ${currentPage <= 1 ? 'hidden' : ''}`}>
prev
</button>
Next Button
<button
onClick={goToNextPage}
className={`next ${currentPage >= pages ? 'hidden' : ''}`}>
next
</button>
Page Numbers
{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
<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
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
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
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!
Top comments (3)
Keep up good work . Amazing article
Great article, you got my follow, keep writing!
Thank you for that!