How to Implement Native Pagination in React

Irakli Tchigladze Feb 02, 2024
How to Implement Native Pagination in React

React is a JavaScript library for building modern Single Page Applications. SPAs are famous for their speed and superior user experience. However, implementing features that provide great UX takes a lot of effort.

Pagination is one of these features, and it’s essential for some applications that contain a lot of data.

Regardless of the complexity of your application, pagination allows you to make sure the page on the website is not overloaded with information. Pagination will enable users to access the content easily.

For instance, if your blog has many posts, it may take a while for the user to find a specific post from years ago. This is much easier to do when there’s a pagination feature, and each page has a particular number of posts.

We can do pagination either on the back-end or front-end. This article aims to discuss implementing the pagination feature natively in React.

Implement Native Pagination in React

To implement a native solution in React, we’ll need to use the state. For instance, we need a state variable currentPage to store an integer to specify which items batch should be displayed.

We’ll also have a state variable to store the number of items displayed on each page. We can have a fixed number of items instead of storing this information in the variable.

However, if we want to change the number of items displayed on each page or let users change it, it’s better to store it in the state. Finally, we should have a state variable to store the items to be displayed.

Let’s take a look at a practical example:

import "./styles.css";
import { useState } from "react";
export default function App() {
    const [items, setItems] = useState([
        "item 1",
        "item 2",
        "item 3",
        "item 4",
        "item 5",
        "item 6",
        "item 7",
        "item 8",
        "item 9",
        "item 10"
    ]);
    const [currentPage, setCurrentPage] = useState(1);
    const [todosPerPage, setTodosPerPage] = useState(3);
    return (
        <div className="App">
        </div>
    );
}

In this code example, we import the useState hook and set up three state variables:

  • items to store the items we need to display,
  • currentPage to store the integer value of the page that needs to be displayed (1 by default), and
  • todosPerPage to store the number of items on each page.

Now, let’s add a little bit of logic to our code.

Since we display a certain number of items on each page, and users can change between pages, we need to figure out which items need to be displayed. We have ten items, with three items on each page, so we’ll have four pages.

The first page will display the first, second, and third items, and so on. We could hard-code which items should be shown for each page, but it’s much wiser to develop a system that can handle any number of items.

Let’s take a look at the logic:

const [currentPage, setCurrentPage] = useState(1);
const [todosPerPage, setTodosPerPage] = useState(3);
const lastTodoInView = currentPage * todosPerPage;
const firstTodoInView = lastTodoInView - todosPerPage;

The two variables, lastTodoInView and firstTodoinView, represent the indexes in the array, which should be the ‘boundaries’ for displaying items on a specific page. For instance, for the first page, assuming that the todosPerPage is set to three, the boundaries will be:

The last: 1 (currentPage) * 3 (todosPerPage) = 3

The first: 3 (lastTodoInView) - 3 (todosPerPage) = 0

Note that in JavaScript, the first item of the array has an index of 0, so the items to display on the first page will have 0, 1, and 2 indexes until they reach 3. The last array index is not inclusive because of how the .slice() method is designed, so our page will not include the item on index 3.

Next, we can use the .slice() method to extract specific values displayed on each page.

const todosForDisplay = items.slice(firstTodoInView, lastTodoInView);

This method takes two arguments, the starting and ending indexes for array items. The starting index is inclusive, meaning that if the first argument is 0, once the method is executed, the new returned array will include the first item.

The ending index is not inclusive, meaning that if the second argument is 3, the returned array will stop at index 2.

Then, we can create a variable to store all the JSX elements generated from the sliced array.

const renderItems = todosForDisplay.map((todo, index) => {
    return <li key={index}>{todo}</li>;
});

It’s advisable to set the key attribute to a unique value so that React can keep track of individual nodes internally.

Later on, we will add the code to allow users to change the currentPage variable, or in simple words, go from one page to another. We could also add the feature to update the number of items displayed on each page, and everything will work properly.

Next, we must generate an array of page numbers. As the number of items in the array grows, so should the number of pages.

For instance, currently, our array has 10 items and 4 pages to display them. If we add 5 more items, we need to calculate how many pages to show them.

Here is the logic to calculate the required number of pages to display all items:

const pageNumbers = [];
for (let n = 1; n <= Math.ceil(items.length / todosPerPage); n++) {
    pageNumbers.push(n);
}

Here, we generate a simple for loop. We start with the initial value of 1 and add it to the pageNumbers array.

We add more and more pages until there are enough pages to display every item. Then we must generate the actual page numbers to display in the application.

To do that, we’ll use the .map() method on the pageNumbers array. Let’s look at the code:

const renderPageNumbers = pageNumbers.map((number, index) => {
    return <li key={index}>{number}</li>;
});

This will generate all the JSX elements that correspond to the page numbers. We have to create an event handler to allow users to move from one page.

This is easily achieved because the useState() hook provides an easy updater function for updating the values. We have to handle the click event, and the event handler function can be as simple as:

const renderPageNumbers = pageNumbers.map((number, index) => {
    return <li onClick={() => setCurrentPage(number)} key={index}>
        {number}
    </li>
});

Finally, our simple pagination system is complete. You can check out the live demo on CodeSandbox and see how everything fits together.

Irakli Tchigladze avatar Irakli Tchigladze avatar

Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.

LinkedIn