How to implement pagination in React Redux Applications?
Last Updated :
13 Mar, 2024
Pagination is a common requirement in web applications. It is very helpful when we wish to display or manage a large dataset on the website in an aesthetic manner. Whenever it comes to displaying a large number of data, state handling comes into the picture. The idea of pagination has a good binding with redux. In this article, we will have a look at how to implement pagination using the redux state management library.
Approach to Implement Pagination in React Redux
In the code, we will make a fetch request to a fake REST API (JSON Placeholder) that serves todos. We will display 10 todos per page. On every page change, 10 more todos will be displayed. To implement this pagination with redux, we will set the initial state of the redux slice with pagination parameters. We will also create an async thunk to fetch todos from the API based on pagiantion state. Along the way, we will include the reducer to update the current page.
Steps to Create React App and Installing Modules
Step 1: Create a react app and enter into the directory created by running the following commands.
npx create-react-app redux-pagination
cd redux-pagination
Step 2: Install the required dependencies
npm install @reduxjs/toolkit react-redux redux-thunk
Project Structure:
project structureUpdated Dependencies: Open package.json to verify the following dependencies.
"dependencies": {
"@reduxjs/toolkit": "^2.2.1",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.0",
"react-scripts": "5.0.1",
"redux-thunk": "^3.1.0",
"web-vitals": "^2.1.4"
}
Example: Here is the working example of pagination using redux in react app.
CSS
/* src/App.css */
/* App.css */
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.top-text {
font-size: 20px;
font-weight: 500;
color: rgb(28, 158, 37);
}
.t-2-text {
font-size: 12px;
text-decoration: underline;
}
.fetch-button {
padding: 10px 20px;
margin-bottom: 20px;
font-size: 16px;
background-color: #f2176b;
color: #fff;
border: none;
border-radius: 3px;
cursor: pointer;
transition: background-color 0.3s;
}
.fetch-button:hover {
background-color: #bf2419;
}
.loading {
margin-top: 20px;
font-size: 60px;
}
.todos-list {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 12px;
font-size: 8px;
}
.cards {
padding: 8px;
border-radius: 5px;
}
.top {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
}
.loader {
width: 20px;
--b: 3px;
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000 10%, #f03355) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg, #000 1deg 20deg, #0000 21deg 36deg),
radial-gradient(farthest-side, #0000 calc(100% - var(--b) - 1px), #000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: l4 1s infinite steps(10);
}
@keyframes l4 {
to {
transform: rotate(1turn)
}
}
.pagination {
display: flex;
gap: 24px;
justify-content: center;
align-items: center;
}
.pagination button {
background-color: rgb(56, 122, 228);
color: white;
padding: 6px 12px;
border-radius: 4px;
border: none;
}
JavaScript
// src/redux/store.js
import { configureStore } from '@reduxjs/toolkit';
import todosReducer from './todoSlice';
const store = configureStore({
reducer: {
todos: todosReducer,
},
});
export default store;
JavaScript
// src/redux/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// Define the number of items per page
const ITEMS_PER_PAGE = 10;
// Define an initial state for pagination
const initialPaginationState = {
currentPage: 1,
totalPages: 1,
totalItems: 0
};
export const fetchTodos = createAsyncThunk(
'todos/fetchTodos',
// Adjust the thunk to use pagination parameters
async (_, { getState }) => {
try {
const { currentPage } = getState().todos.pagination;
const start = (currentPage - 1) * ITEMS_PER_PAGE;
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos?_start=${start}&_limit=${ITEMS_PER_PAGE}`);
if (!response.ok) {
throw new Error('Failed to fetch todos');
}
const totalCountHeader = response.headers.get('x-total-count');
const totalItems =
totalCountHeader ?
parseInt(totalCountHeader, 10) : 0;
const todos = await response.json();
return { todos, totalItems };
} catch (error) {
throw new Error('Error fetching todos');
}
}
);
const todosSlice = createSlice({
name: 'todos',
initialState: {
data: [],
loading: false,
error: null,
pagination: initialPaginationState
// Include pagination state in initial state
},
reducers: {
// Add a reducer to update current page
setCurrentPage: (state, action) => {
state.pagination.currentPage = action.payload;
}
},
extraReducers: (builder) => {
builder
.addCase(fetchTodos.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchTodos.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload.todos;
state.pagination.totalItems = action.payload.totalItems;
state.pagination.totalPages =
Math.ceil(action.payload.totalItems / ITEMS_PER_PAGE);
})
.addCase(fetchTodos.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
},
});
// Export setCurrentPage action
export const { setCurrentPage } = todosSlice.actions;
export default todosSlice.reducer;
JavaScript
// src/App.js
import React,
{
useEffect
} from 'react';
import {
useDispatch,
useSelector
} from 'react-redux';
import { fetchTodos, setCurrentPage } from './redux/todoSlice';
import './App.css';
import Loader from './components/Loader';
function App() {
const dispatch = useDispatch();
const todos = useSelector((state) => state.todos);
const randomLightColor = () => {
const randomColor =
() =>
Math.floor(Math.random() * 200) + 56;
return `rgb(${randomColor()}, ${randomColor()}, ${randomColor()})`;
};
useEffect(() => {
dispatch(fetchTodos());
}, [dispatch]);
// Fetch todos on component mount
const handlePrevPage = () => {
if (todos.pagination.currentPage > 1) {
dispatch(setCurrentPage(todos.pagination.currentPage - 1));
dispatch(fetchTodos());
}
};
const handleNextPage = () => {
if (todos.pagination.currentPage < todos.pagination.totalPages) {
dispatch(setCurrentPage(todos.pagination.currentPage + 1));
dispatch(fetchTodos());
}
};
return (
<div className="container">
<div className='top'>
<h1 className='top-text'>GFG Todo Display App</h1>
</div>
<div className='top'>
{todos.loading && <p className="loading"><Loader /></p>}
<div className="todos-list">
{todos.data?.map((todo) => (
<div className='cards'
style={{backgroundColor:randomLightColor()}}
key={todo.id}>{todo.title}</div>
))}
</div>
<div className="pagination">
<button className="pagination-button"
onClick={handlePrevPage}
disabled={todos.pagination.currentPage === 1}>
prev
</button>
<span className="pagination-info">
Page {todos.pagination.currentPage}
of {todos.pagination.totalPages}
</span>
<button className="pagination-button"
onClick={handleNextPage}
disabled={todos.pagination
.currentPage === todos.pagination
.totalPages}>
next
</button>
</div>
</div>
</div>
);
}
export default App;
JavaScript
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
JavaScript
// src/components/Loader.js
import React from 'react'
const Loader = () => {
return (
<div className='loader'></div>
)
}
export default Loader
Output:
npm start

Similar Reads
How to Implement Caching in React Redux applications ?
Caching is the practice of storing frequently used or calculated data temporarily in memory or disk. Its main purpose is to speed up access and retrieval by minimizing the need to repeatedly fetch or compute the same information. By doing so, caching helps reduce latency, conserve resources, and ult
3 min read
How to implement pagination in React using Hooks?
Implementing pagination in React using hooks involves managing the state of the current page and the number of items per page, as well as rendering the paginated data accordingly. Implementing pagination in React using Hooks:Setup Initial State: Use the useState hook to manage the state for the curr
3 min read
How To Implement Code Splitting in Redux Applications?
Code splitting in Redux applications refers to the practice of breaking down the application into smaller, manageable chunks that can be loaded on demand. This helps in reducing the initial load time of the application by only loading the necessary parts of the application when needed. Dynamic impor
3 min read
How To Implement Navigation In React JS ?
React router is a powerful library that enables developers to manage navigation in a React application. It provides a way to define the routes and their corresponding components, allowing for a good user experience while navigating between different parts of any application. In this article, we will
2 min read
How to Optimize the Performance of React-Redux Applications?
Optimizing the performance of React-Redux applications involves several strategies to improve loading speed, reduce unnecessary re-renders, and enhance user experience. In this article, we implement some optimization techniques, that can significantly improve the performance of applications. We will
9 min read
How to Normalize State in Redux Applications ?
In Redux applications, efficient state management is essential for scalability and maintainability. Normalization is a technique used to restructure complex state data into a more organized format, improving performance and simplifying state manipulation. This article covers the concept of normaliza
3 min read
How does React Router handle navigation in a React application?
React Router is a standard library for routing in React. It enables the navigation among views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL. Let us create a simple application to React to understand how the React Router works Re
3 min read
How to Log and Display Errors in React-Redux Applications?
In this article, we make a React-Redux application to manage and display errors. We create actions ( CLEAR_ERROR ) for managing errors and ErrorDisplay components to display errors. We implementing an error reducer to manage the error state and connect it to the redux store. Approach to Implement lo
3 min read
Implementing Pagination and Infinite Scrolling with React Hooks
This article will discuss pagination and infinite scrolling. These concepts are commonly used in web applications to enhance the user experience. Pagination and infinite scrolling both help in the efficient handling of huge data sizes. Approach to Implement Pagination and Infinite Scrolling:Paginati
6 min read
How To Implement Multiple Filters In React ?
Applying Filters in React applications is important for enhancing user experience by allowing users to customize the displayed content based on their preferences. In this article, we will explore two approaches to implementing Multiple Filters in React. Table of Content Using State HooksUsing Contex
5 min read