In this tutorial, I will show you how to make Pagination in a React Application with existing API using Material-UI.
Related Posts:
– React Material UI examples with a CRUD Application
– Form Validation: React Hook Form & Material UI example
– React File Upload with Axios and Progress Bar to Rest API
– React JWT Authentication (without Redux) example
Using Hooks:
– React Pagination using Hooks example
– React Table Pagination (Server side) with Search | react-table v7
Contents
- React Pagination with API overview
- React Pagination using Material-UI
- Technology
- Setup React.js Application
- Setup Material-UI for React Pagination App
- Initialize Axios for React HTTP Client
- Create Data Service
- Create React Components with Pagination
- Configure Port for Web API
- Run React Pagination App
- Conclusion
- Further Reading
- Source Code
React Pagination with API overview
One of the most important things to make a website friendly is the response time, and pagination comes for this reason. For example, this bezkoder.com website has hundreds of tutorials, and we don’t want to see all of them at once. Paging means displaying a small number of all, by a page.
Assume that we have tutorials table in database like this:
Our React.js app will display the result with pagination:
Change to a page with larger index:
We can change quantity of items per page:
Or paging with filter:
The API for this React client can be found at one of following posts:
– Node.js Express Pagination with MySQL
– Node.js Express Pagination with PostgreSQL
– Node.js Express Pagination with MongoDB
– Spring Boot Pagination & Filter example | Spring JPA, Pageable
– Spring Boot MongoDB Pagination example with Spring Data
These Servers will exports API for pagination (with/without filter), here are some url samples:
/api/tutorials?page=1&size=5
/api/tutorials?size=5
: using default value for page/api/tutorials?page=1
: using default value for size/api/tutorials?title=data&page=1&size=3
: pagination & filter by title containing ‘data’
This is structure of the response for the HTTP GET request:
{
"totalItems": 8,
"tutorials": [...],
"totalPages": 3,
"currentPage": 1
}
We actually only need to use tutorials
and totalPages
when working with Material-UI.
React Pagination using Material-UI
Material-UI provides Pagination component that enables the user to select a specific page from a range of pages.
For example, with Pagination
components below:
<Pagination count={10} />
<Pagination count={10} color="primary" />
<Pagination count={10} variant="outlined" />
<Pagination count={10} variant="outlined" color="primary" />
<Pagination count={10} shape="rounded" />
<Pagination count={10} variant="outlined" shape="rounded" />
We’re gonna have UI like this-
There are also 2 optional props for Ranges:
siblingRangespecify
: how many digits to display either side of current pageboundaryRange
: adjacent to the start and end page number
For example:
<Pagination count={11} defaultPage={6} siblingCount={0} />
<Pagination count={11} defaultPage={6} /> {/* Default ranges */}
<Pagination count={11} defaultPage={6} siblingCount={0} boundaryCount={2} />
<Pagination count={11} defaultPage={6} boundaryCount={2} />
For handling page changes, we use onChange
:
export default function PaginationControlled() {
const [page, setPage] = React.useState(1);
const handleChange = (event, value) => {
setPage(value);
};
return (
<div>
<Pagination count={10} page={page} onChange={handleChange} />
</div>
);
}
Notice that count
is totalPages
in the API response, and page
is the current page.
Technology
- React 16
- axios 0.19.2
- material-ui 4
Setup React.js Application
Open cmd at the folder you want to save Project folder, run command:
npx create-react-app react-pagination-material-ui
After the process is done. We create additional folders and files like the following tree:
public
src
components
add-tutorial.component.js
tutorial.component.js
tutorials-list.component.js
services
tutorial.service.js
App.css
App.js
index.js
package.json
You can follow step by step, or get source code in this post:
React Material UI examples with a CRUD Application
The React Project contains structure that we only need to add some changes (in tutorials-list.component.js and tutorial.service.js) to make the pagination work well.
Or you can get the new Github source code at the end of this tutorial.
Setup Material-UI for React Pagination App
We need to install both Material-UI core and lab with command:
npm install @material-ui/core @material-ui/lab
Initialize Axios for React HTTP Client
Let’s install axios with command: npm install axios
.
Under src folder, we create http-common.js file with following code:
import axios from "axios";
export default axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-type": "application/json"
}
});
For more details about ways to use Axios, please visit:
Axios request: Get/Post/Put/Delete example
Create Data Service
In this step, we’re gonna create a service that uses axios
object above to send HTTP requests.
services/tutorial.service.js
import http from "../http-common";
class TutorialDataService {
getAll(params) {
return http.get("/tutorials", { params });
}
// other CRUD methods
}
export default new TutorialDataService();
In the code above, you can see that we pass params
object to GET method.
The params
object will have one, two or all fields: title
, page
, size
.
Create React Components with Pagination
This component has:
- a search bar for finding Tutorials by title.
- a select element for quantity of items per page.
- a Material-UI Pagination component
- a tutorials array displayed as a list on the left.
- a selected Tutorial which is shown on the right.
So we will have following state:
– search and display Tutorials:
searchTitle
tutorials
currentTutorial
andcurrentIndex
– pagination:
page
: current pagecount
: total pagespageSize
: number of items in each page
For pagination, we need to use TutorialDataService.getAll()
methods.
components/tutorials-list.component.js
import React, { Component } from "react";
import TutorialDataService from "../services/tutorial.service";
...
export default class TutorialsList extends Component {
constructor(props) {
super(props);
this.onChangeSearchTitle = this.onChangeSearchTitle.bind(this);
this.retrieveTutorials = this.retrieveTutorials.bind(this);
this.refreshList = this.refreshList.bind(this);
this.setActiveTutorial = this.setActiveTutorial.bind(this);
this.removeAllTutorials = this.removeAllTutorials.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
this.handlePageSizeChange = this.handlePageSizeChange.bind(this);
this.state = {
tutorials: [],
currentTutorial: null,
currentIndex: -1,
searchTitle: "",
page: 1,
count: 0,
pageSize: 3,
};
this.pageSizes = [3, 6, 9];
}
componentDidMount() {
this.retrieveTutorials();
}
onChangeSearchTitle(e) {
const searchTitle = e.target.value;
this.setState({
searchTitle: searchTitle,
});
}
getRequestParams(searchTitle, page, pageSize) {
let params = {};
if (searchTitle) {
params["title"] = searchTitle;
}
if (page) {
params["page"] = page - 1;
}
if (pageSize) {
params["size"] = pageSize;
}
return params;
}
retrieveTutorials() {
const { searchTitle, page, pageSize } = this.state;
const params = this.getRequestParams(searchTitle, page, pageSize);
TutorialDataService.getAll(params)
.then((response) => {
const { tutorials, totalPages } = response.data;
this.setState({
tutorials: tutorials,
count: totalPages,
});
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
}
...
handlePageChange(event, value) {
this.setState(
{
page: value,
},
() => {
this.retrieveTutorials();
}
);
}
handlePageSizeChange(event) {
this.setState(
{
pageSize: event.target.value,
page: 1
},
() => {
this.retrieveTutorials();
}
);
}
render() {
...
}
}
Let me explain some lines of code.
In the retrieveTutorials()
method:
– We get searchTitle
, page
, pageSize
state and transform them into params
object:
{
"title": searchTitle,
"page": page - 1,
"size": pageSize
}
– We use tutorials
and totalPages
as count
state from the response data:
{
"totalItems": 8,
"tutorials": [...],
"totalPages": 3,
"currentPage": 1
}
handlePageChange()
and handlePageSizeChange()
methods are for setting new page
and pageSize
with callback invoking retrieveTutorials()
that updates the tutorials List when pagination information changes.
Let’s continue to implement render()
method:
...
import Pagination from "@material-ui/lab/Pagination";
export default class TutorialsList extends Component {
...
render() {
const {
searchTitle,
tutorials,
currentTutorial,
currentIndex,
page,
count,
pageSize,
} = this.state;
return (
<div className="list row">
<div className="col-md-8">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="Search by title"
value={searchTitle}
onChange={this.onChangeSearchTitle}
/>
<div className="input-group-append">
<button
className="btn btn-outline-secondary"
type="button"
onClick={this.retrieveTutorials}
>
Search
</button>
</div>
</div>
</div>
<div className="col-md-6">
<h4>Tutorials List</h4>
<div className="mt-3">
{"Items per Page: "}
<select onChange={this.handlePageSizeChange} value={pageSize}>
{this.pageSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
<Pagination
className="my-3"
count={count}
page={page}
siblingCount={1}
boundaryCount={1}
variant="outlined"
shape="rounded"
onChange={this.handlePageChange}
/>
</div>
<ul className="list-group">
{tutorials &&
tutorials.map((tutorial, index) => (
<li
className={
"list-group-item " +
(index === currentIndex ? "active" : "")
}
onClick={() => this.setActiveTutorial(tutorial, index)}
key={index}
>
{tutorial.title}
</li>
))}
</ul>
</div>
...
</div>
);
}
}
You can simplify import statement with:
Absolute Import in React
Configure Port for Web API
Because most of HTTP Server use CORS configuration that accepts resource sharing retricted to some sites or ports, so we also need to configure port for our App.
In project folder, create .env file with following content:
PORT=8081
Now we’ve set our app running at port 8081
.
Run React Pagination App
First you need to run the Server at one of following posts:
- Node.js Express Pagination with MySQL
- Node.js Express Pagination with PostgreSQL
- Node.js Express Pagination with MongoDB
- Spring Boot Pagination & Filter example | Spring JPA, Pageable
- Spring Boot MongoDB Pagination example with Spring Data
Then you can run our App with command: npm start
.
If the process is successful, open Browser with Url: http://localhost:8081/
and check it.
Conclusion
Today we’ve built a React Pagination example that consume API successfully with Material UI. I hope you apply it in your project at ease.
If you want to use React Hooks instead of Components, please visit:
– React Pagination using Hooks example
– React Table Pagination (Server side) with Search | react-table v7
This tutorial code is based on CRUD project:
React Material UI examples with a CRUD Application
Form Validation: React Hook Form & Material UI example
Happy learning, see you again!
Further Reading
- https://material-ui.com/components/pagination/
- https://www.npmjs.com/package/@material-ui/core
- https://www.npmjs.com/package/@material-ui/lab
For more details about ways to use Axios, please visit:
Axios request: Get/Post/Put/Delete example
Source Code
You can find the complete source code for this tutorial on Github.
It’s very simple to find out way to implement MUI Pagination with this tutorial. Thanks!
best tutorials for React pagination! thnk
Hey. One weird bug I encountered during search was, when I move to a page other than page_1 and search for something, I’m getting the data from the API, but the table was empty, but I can see page number 1 in the pagination.
I guess, after a search operation, the page number shud be set to 1. That shud work hopefully.
Cheers 🙂
Great work bez. I’m a big fan of your tutorials. Cheers
Thanks for sharing this with us. I have little problem, in console Json loaded successfull but Tutorials List not showing on list-group
Hey I am so excited I found your tutorial. Many thanks!
Hello, I am Serena and I liked your tutorials a lot. You really did a great job. The article is Very Interesting and Informative at the same time, thanks for sharing this with us.
Please I need Vue Pagination and Sorting with Spring Boot API Example.
Thanks.
Hi, I’ve written a tutorial for Vue Pagination:
Vue Pagination with Axios and API example