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.
- Setting up files
- Writing code to fetch data
- Writing the Pagination Component
- 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
or you can also code on codesandbox
or stackblitz
After the app is created, your folder structure might look like this
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;
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 };
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>
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;
}
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>
Once you have written all the code, run
npm start
The whole code and demo is uploaded on github.
Happy Coding!
Top comments (0)