How to create a Pagination in React JS with Spring Boot Application? In this article, we will learn How to create a Pagination in React JS with Spring Boot Application.
Tools and Technologies Used in Spring boot and ReactJs app
- React JS
- Spring Boot
- MYSQL Database
- Spring Data JPA
Pagination using React JS and Spring Boot with MYSQL
We will develop a simple application where we will fetch the list of Books from the database on the web page using React JS as a front-end technology and Spring Boot as a Backend technology.
Here, we will perform pagination on the data and will display a large set of data in chunks. If you want to know more about Spring Boot check this article https://codedec.com/course/spring-boot/.
Let us divide the development process into two parts:
- Frontend: React JS
- Backend: Spring Boot
Note: If you want to know How to display only the list on the web page using React JS and Spring Boot application check this article https://codebun.com/how-to-create-spring-boot-and-reactjs-application/.
Create Backend Part using Spring boot, Spring Data JPA and MYSQL
Create a Database
The first step is to create a database name ‘db_demo’ using the MYSQL command line or Workbench.
Create database db_demo
Create Project
Create a project using Spring Initializr. If you don’t know how to create a project using the same check this article https://codedec.com/tutorials/how-to-create-spring-boot-project-using-spring-initializr/

Import a Project
Now, it’s time to import the project into STS. Go to File > Import > Maven > Existing Maven Project > Next > Browse > Select the project > Finish. Now it will take time to import the project and will import all the dependencies in case you added.
Configure application. properties file
# change the port server.port=8888 #Database Configrations spring.datasource.url=jdbc:mysql://localhost:3306/db_demo spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=root spring.jpa.database-platform = org.hibernate.dialect.MySQL8Dialect spring.jpa.generate-ddl=true spring.jpa.hibernate.ddl-auto = update
Create a Model Class
Here, we will create a Model class called Book.java. I have used the Lombok library to remove boilerplate code. In case you want to know what is Lombok check this article https://codedec.com/tutorials/how-to-configure-lombok-into-eclipse/
Book.java
package com.abc.in.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String bookName;
private String authorName;
private long price;
}
Create Repository Interface
Now, we will create a Data Access Layer called BookRepository which will extend JPARepository. If you want to know How to add dynamic pagination using Spring Data JPA check this article Pagination.
package com.abc.in.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.abc.in.model.Book;
public interface BookRepository extends JpaRepository<Book, Long>{
}
Create a Controller
The client request is sent to the controller which acts as an API layer that will have the endpoints for REST API.
package com.abc.in.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.abc.in.model.Book;
import com.abc.in.repository.BookRepository;
@CrossOrigin(origins = "http://localhost:3000/")
@RestController
public class BookController {
@Autowired
private BookRepository bookRepository;
@GetMapping("/books")
public Page<Book> getAllBooks(Pageable pageable) {
return bookRepository.findAll(pageable);
}
}
- Mark this class as @RestController(It is used to simplify the creation of REST APIs).
- Here, we have a repository method findAll(Pageable pageable) that will return the Page object. Thus, this page object will return the list.
Now, Here you can add multiple records directly into a table using MYSQL workbench or you can implement the CommandLineRunner interface as shown below.
package com.abc.in;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.abc.in.model.Book;
import com.abc.in.repository.BookRepository;
@SpringBootApplication
public class SpringBootBackendPartApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(SpringBootBackendPartApplication.class, args);
}
@Autowired
private BookRepository bookRepository;
@Override
public void run(String... args) throws Exception {
Book book = new Book();
for (int i = 0; i < 30; i++) {
bookRepository.save(new Book(1, "Wings of Fire", "A P J Abdul Kalam, Arun Tiwari", 500 + i));
bookRepository.save(new Book(2, "The Alchemist", "Paulo Coelho", 144 + i));
bookRepository.save(new Book(3, "War and Peace", "Leo Tolstoy", 299 + i));
bookRepository.save(new Book(3, "Song of Solomon", "Tony Morrison", 555 + i));
}
}
}
Run the Application
Run the above class and see the data would now be persisted into the table. Go to the browser and hit the URL http://localhost:8888/books?page=0&size=5 and you will see the response in JSON format along with some more data such as Pagination data.
Create Frontend Part using ReactJS
Now, we will create a frontend part of the application using React JS. Open Cmd prompt > Go to the folder where you want to create a project with the help of command prompt codes > enter the command npx create-react-app book-frontend.
- Now, open Visual Studio Code IDE and open the book-frontend app.
- Here, you will see all the required folders and files.
We will be using bootstrap in React JS. So, open the terminal of VS code and type the following command
D:\Job Stuff\My_Study\React JS\book-frontend>npm install bootstrap
You have to install React Bootstrap also by using the following command
D:\Job Stuff\My_Study\React JS\book-frontend> npm install react-bootstrap
Install Axios library that is going to make a request to the endpoints which we have created at the backend.
D:\Job Stuff\My_Study\React JS\book-frontend> npm install axios
Create BookComponent.js
Inside the src folder, create a components folder and add a BookComponent.js and add the following lines of code.
import axios from 'axios';
import React from 'react'
import { Button, Row } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import bookService from '../services/BookService'
class BookComponent extends React.Component{
constructor(props){
super(props)
this.state ={
books:[],
currentPage:1,
recordPerPage:7,
}
}
componentDidMount(){
this.getBooksByPagination(this.state.currentPage);
}
getBooksByPagination(currentPage){
currentPage=currentPage-1;
axios.get("http://localhost:8888/books?page="+currentPage+"&size="+this.state.recordPerPage)
.then(response => response.data).then((data) =>{
this.setState({books:data.content,
totalPages:data.totalPages,
totalElements: data.totalElements,
currentPage: data.number+1
});
});
}
//Writing All the pagination functions
//Show Next page
showNextPage = () =>{
if(this.state.currentPage < Math.ceil(this.state.totalElements/this.state.recordPerPage)){
this.getBooksByPagination(this.state.currentPage + 1);
}
};
//Show Last Page
showLastPage = () =>{
if(this.state.currentPage < Math.ceil(this.state.totalElements/this.state.recordPerPage)){
this.getBooksByPagination(Math.ceil(this.state.totalElements/this.state.recordPerPage));
}
};
//Show First page
showFirstPage = ()=>{
let firstPage = 1;
if(this.state.currentPage > firstPage){
this.getBooksByPagination(firstPage);
}
};
//Show previous page
showPrevPage = () =>{
let prevPage = 1
if(this.state.currentPage > prevPage){
this.getBooksByPagination(this.state.currentPage - prevPage);
}
};
render(){
const {books, currentPage, totalPages,recordPerPage} = this.state;
return(
<div>
<h1 className="text-center mt-5 ">List of Books</h1>
<div className="container mt-2">
<table className="table table-bordered border-info shadow">
<thead>
<tr>
<th>#</th>
<th>Book Name</th>
<th>Book Author</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{books.length===0?
<tr align="center"><td colSpan="5">No Record Found</td></tr>:
books.map(
(books,index) =>(
<tr key = {books.id}>
<td>{(recordPerPage*(currentPage-1))+index+1}</td>
<td>{books.bookName}</td>
<td>{books.authorName}</td>
<td>{books.price}</td>
</tr>
)
)
}
</tbody>
</table>
<table className="table">
<div style={{float:'left',fontFamily: 'monospace',color: '#0275d8'}}>
Page {currentPage} of {totalPages}
</div>
<div style={{float:'right'}}>
<div class="clearfix"></div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===1?true:false} onClick={this.showPrevPage}>Previous</a></li>
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===1?true:false } onClick={this.showFirstPage}>First</a></li>
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===totalPages?true:false } onClick={this.showNextPage}>Next</a></li>
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===totalPages?true:false} onClick={this.showLastPage}>Last</a></li>
</ul>
</nav>
</div>
</table>
</div>
</div>
)
}
}
export default BookComponent
Now, let us divide the code and understand the working of it. First, add a constructor with props to pass data and use the state to manage the data as shown below. Here, set the currentPage and recordPerPage value to 1 and 7.
constructor(props){
super(props)
this.state ={
books:[],
currentPage:1,
recordPerPage:7,
}
}
Now, add the componentDidMount() method which will be called after a component is mounted. Inside this method call the getBooksByPagination.
componentDidMount(){
this.getBooksByPagination(this.state.currentPage);
}
Now, define getBooksByPaginatination method. Inside this method, use the Axios library to make the request to the endpoints and set the state with the response data.
getBooksByPagination(currentPage){
currentPage=currentPage-1;
axios.get("http://localhost:8888/books?page="+currentPage+"&size="+this.state.recordPerPage)
.then(response => response.data).then((data) =>{
this.setState({books:data.content,
totalPages:data.totalPages,
totalElements: data.totalElements,
currentPage: data.number+1
});
});
}
Now, create all the Pagination functions such as showNextPage(), showPrevPage() and so on that would be called on the Next, Previous button/link.
//Writing All the pagination functions
//Show Next page
showNextPage = () =>{
if(this.state.currentPage < Math.ceil(this.state.totalElements/this.state.recordPerPage)){
this.getBooksByPagination(this.state.currentPage + 1);
}
};
//Show Last Page
showLastPage = () =>{
if(this.state.currentPage < Math.ceil(this.state.totalElements/this.state.recordPerPage)){
this.getBooksByPagination(Math.ceil(this.state.totalElements/this.state.recordPerPage));
}
};
//Show First page
showFirstPage = ()=>{
let firstPage = 1;
if(this.state.currentPage > firstPage){
this.getBooksByPagination(firstPage);
}
};
//Show previous page
showPrevPage = () =>{
let prevPage = 1
if(this.state.currentPage > prevPage){
this.getBooksByPagination(this.state.currentPage - prevPage);
}
};
At last, the render() method would return the view that would be rendered by the browser. Here, we create a table to show the list as well as the Pagination table also. we have used the map() function to iterate over the list.
render(){
const {books, currentPage, totalPages,recordPerPage} = this.state;
return(
<div>
<h1 className="text-center mt-5 ">List of Books</h1>
<div className="container mt-2">
<table className="table table-bordered border-info shadow">
<thead>
<tr>
<th>#</th>
<th>Book Name</th>
<th>Book Author</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{books.length===0?
<tr align="center"><td colSpan="5">No Record Found</td></tr>:
books.map(
(books,index) =>(
<tr key = {books.id}>
<td>{(recordPerPage*(currentPage-1))+index+1}</td>
<td>{books.bookName}</td>
<td>{books.authorName}</td>
<td>{books.price}</td>
</tr>
)
)
}
</tbody>
</table>
<table className="table">
<div style={{float:'left',fontFamily: 'monospace',color: '#0275d8'}}>
Page {currentPage} of {totalPages}
</div>
<div style={{float:'right'}}>
<div class="clearfix"></div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===1?true:false} onClick={this.showPrevPage}>Previous</a></li>
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===1?true:false } onClick={this.showFirstPage}>First</a></li>
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===totalPages?true:false } onClick={this.showNextPage}>Next</a></li>
<li class="page-item"><a type="button" class="page-link" disabled={currentPage===totalPages?true:false} onClick={this.showLastPage}>Last</a></li>
</ul>
</nav>
</div>
</table>
</div>
</div>
)
Here, to display serial numbers in increment order, we have used the following lines of code
<td>{(recordPerPage*(currentPage-1))+index+1}</td>
Now, add the BookComponent.js into App.js
import logo from './logo.svg';
import './App.css';
import BookComponent from './components/BookComponent';
function App() {
return (
<div className="App">
<BookComponent/>
</div>
);
}
export default App;
Run the React JS app by going to the terminal and enter the following command
D:\Job Stuff\My_Study\React JS\book-frontend> npm start
At localhost:3001 you will be able to see the following output:


In this way, we learned how to apply dynamic pagination in React JS with the Spring boot application.
ReactJs and Spring boot Application examples
https://codebun.com/how-to-insert-data-into-mysql-using-react-js-and-spring-boot/
https://codebun.com/edit-and-update-records-in-react-js-using-spring-boot-and-mysql/
https://codebun.com/delete-record-from-a-table-in-react-js-spring-boot-and-mysql/
https://codebun.com/search-record-from-a-table-in-react-js-spring-boot-and-mysql/
https://codebun.com/how-to-create-a-pagination-in-react-js-and-spring-boot/
https://codebun.com/how-to-create-spring-boot-and-reactjs-application/