Build this pagination in your React

I have data that is fetched from the API, and I would like to paginate this data. In this post, I’m going to implement pagination using React.

Requirement

Suppose that the API returns for me the total page value, and I need to use this valu…


This content originally appeared on DEV Community and was authored by Phan Công Thắng

I have data that is fetched from the API, and I would like to paginate this data. In this post, I’m going to implement pagination using React.

Requirement

Suppose that the API returns for me the total page value, and I need to use this value to make pagination. And I also need to have the current page in case the user moves on other pages.

This is the requirement:

Simple Requirement

Flow

Now, we had the simple requirement. I'm going to draw the flow before moving the coding step.

In this example, I think I need to have:

  1. Render all pages based on the total page value.
  2. A state pageIndex which points to the current page.

Coding

First of all, we need to have a Next.js project. Let's do it quickly!

npx create-next-app@latest --typescript

Step1: Render all pages using the total page value.

Just for the demo, so I'm going to hard code the total page value. I set it to 20.

import type {NextPage} from 'next'
import styles from '../styles/Home.module.css'

const PAGE_TOTAL = 20

const Home: NextPage = () => {
  return (
    <div className={styles.container}>
      <ul className={styles.pagination}>
        {Array.from({length: PAGE_TOTAL}, (_, idx) => (
          <li className={styles.pageItem}>{idx + 1}</li>
        ))}
      </ul>
    </div>
  )
}

export default Home

Notice how I render the pages, and the number of the page just use Array.from and idx + 1.

Step2: Make the current page.

In this step, I need to make the current page.

First, define a new state in React:

const [pageIndex, setPageIndex] = React.useState(0)

By default, the current page is 0.

Next, add a function that helps us to change the current page.

function handlePageChange(idx: number) {
  setPageIndex(idx)
}

Finally, add the style for the current page, and the onClick event.

<li
  className={`${styles.pageItem} ${
    idx === pageIndex ? styles.currentPage : ''
  }`}
  onClick={() => handlePageChange(idx)}
>
  {idx + 1}
</li>

Now, we are able to change the current page.

Page Changing

So far, we almost finished the pagination. But suppose that I only want to render 5 pages on the screen, and whenever I click on another page, the pages automatically increase.

Can I make it?

Yes, Let's go forward!

Next requirement

In this section, we are going to make our pagination more interactive. We need to render 5 pages on the screen, and the other pages automatically change based on the current page.

For ease of imagination, take a look at the image below:

New Requirement

Next Flow

Based on the requirement above, to implement the new pagination, I need to make a new flow for my pagination.

We have three cases:

  1. The total page value is less than 5.
  2. The total page value is greater than 5 plus the pageIndex value.
  3. The total page value is less than 5 plus the pageIndex value.

Let's break down these cases above in more detail!

The total page value is less than 5.

I set the total page value is 20, it definitely doesn't happen. But in the real world, maybe it will happen.

In this case, we don't need to change the logic code anymore. Just keep the code in the previous requirement.

The total page value is greater than 5 plus the pageIndex value.

Whenever we click the new page, the clicked page will move on the first positions and the remaining pages automatically are rendered.

The Second Case

The total page value is less than 5 plus the pageIndex value.

In this case, we can't automatically increase the pages, just change the current page value.

The Third Case

Next Coding

We need to change three things in the previous code:

  • The number of the page.
  • The total pages is rendered on the screen.
  • The function which we use in order to change the current page.
  • The current page logic.

The total page value is less than 5.

<li
  className={`${styles.pageItem} ${
    idx === pageIndex ? styles.currentPage : ''
  }`}
  onClick={() => handlePageChange(idx)}
>
  {idx + 1}
</li>

The total page value is greater than 5 plus the pageIndex value.

In this case, we need to implement these requirements below:

  • The number of the page is the current page index plus current index where we clicked.
  • The total pages: 5.
  • The current page index always zero.
{
  Array.from({length: 5}, (_, idx) => (
    <li
      className={`${styles.pageItem} ${idx === 0 ? styles.currentPage : ''}`}
      onClick={() => handlePageChange(pageIndex + idx)}
    >
      {pageIndex + idx + 1}
    </li>
  ))
}

The total page value is less than 5 plus the pageIndex value.

In this case, we need to implement these requirements below:

  • The right pages that are calculated from the current page index to the total page value, it's not equal to 5, so we need to take the remaining pages on the left side and the start index is the first page in the left side pages.
  • The total pages: 5.
  • The current page index always zero.
const PAGE_TOTAL = 20

const Home: NextPage = () => {
  const [pageIndex, setPageIndex] = React.useState(17)

  function handlePageChange(idx: number) {
    setPageIndex(idx)
  }

  // the right pages: 18,19,20
  // the left pages: 16,17
  // the start index: 15(page 16)
  const numberOfRightPages = PAGE_TOTAL - pageIndex
  const numberOfLeftPages = 5 - numberOfRightPages
  const startPageIndex = pageIndex - numberOfLeftPages

  return (
    <div className={styles.container}>
      <ul className={styles.pagination}>
        {Array.from({length: 5}, (_, idx) => (
          <li
            key={`pagination-items-${idx}`}
            className={`${styles.pageItem} ${
              startPageIndex + idx === pageIndex ? styles.currentPage : ''
            }`}
            onClick={() => handlePageChange(startPageIndex + idx)}
          >
            {startPageIndex + idx + 1}
          </li>
        ))}
      </ul>
    </div>
  )
}

Next Page Changing

Improvement

We have three cases, consider these cases, there are four different logic.

  1. The number of page.
  2. The current page check.
  3. The page index.
  4. The total page.

And we can improve our code by writing the component using
Inversion of Control method.

import type {NextPage} from 'next'
import styles from '../styles/Home.module.css'
import * as React from 'react'

const PAGE_TOTAL = 20
const NUMBER_PAGE = 5

function Pagination({
  length,
  isCurrentPage,
  goToNewPage,
  makeNumberPage,
}: {
  length: number
  isCurrentPage: (idx: number) => boolean
  goToNewPage: (idx: number) => void
  makeNumberPage: (idx: number) => number
}) {
  return (
    <ul className={styles.pagination}>
      {Array.from({length}, (_, idx) => (
        <li
          className={`${styles.pageItem} ${
            isCurrentPage(idx) ? styles.currentPage : ''
          }`}
          onClick={() => goToNewPage(idx)}
        >
          {makeNumberPage(idx)}
        </li>
      ))}
    </ul>
  )
}

const Home: NextPage = () => {
  const [pageIndex, setPageIndex] = React.useState(0)

  function handlePageChange(idx: number) {
    setPageIndex(idx)
  }

  if (PAGE_TOTAL < NUMBER_PAGE) {
    return (
      <Pagination
        length={PAGE_TOTAL}
        isCurrentPage={(idx) => idx === pageIndex}
        goToNewPage={(idx) => handlePageChange(idx)}
        makeNumberPage={(idx) => idx + 1}
      />
    )
  }

  if (PAGE_TOTAL >= pageIndex + NUMBER_PAGE) {
    return (
      <Pagination
        length={NUMBER_PAGE}
        isCurrentPage={(idx) => idx === 0}
        goToNewPage={(idx) => handlePageChange(pageIndex + idx)}
        makeNumberPage={(idx) => pageIndex + idx + 1}
      />
    )
  }

  if (PAGE_TOTAL < pageIndex + NUMBER_PAGE) {
    // the right pages: 18,19,20
    // the left pages: 16,17
    // the start index: 15(page 16)
    const numberOfRightPages = PAGE_TOTAL - pageIndex
    const numberOfLeftPages = NUMBER_PAGE - numberOfRightPages
    const startPageIndex = pageIndex - numberOfLeftPages

    return (
      <Pagination
        length={NUMBER_PAGE}
        isCurrentPage={(idx) => startPageIndex + idx === pageIndex}
        goToNewPage={(idx) => handlePageChange(startPageIndex + idx)}
        makeNumberPage={(idx) => startPageIndex + idx + 1}
      />
    )
  }

  throw new Error(`Just avoid the error comes from typescript!`)
}

export default Home

And we have the new pagination!

Five Page Changing

You can change the NUMBER_PAGE value, e.g: I change it to 7.

Seven Page Changing

Conclusion

We just created pagination in a React app. In the first example, everything seems easy, but if we add some features to our pagination we need more code than we think. So why don't think some ideal for your pagination and play with it?


This content originally appeared on DEV Community and was authored by Phan Công Thắng


Print Share Comment Cite Upload Translate Updates
APA

Phan Công Thắng | Sciencx (2021-11-07T02:40:11+00:00) Build this pagination in your React. Retrieved from https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/

MLA
" » Build this pagination in your React." Phan Công Thắng | Sciencx - Sunday November 7, 2021, https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/
HARVARD
Phan Công Thắng | Sciencx Sunday November 7, 2021 » Build this pagination in your React., viewed ,<https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/>
VANCOUVER
Phan Công Thắng | Sciencx - » Build this pagination in your React. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/
CHICAGO
" » Build this pagination in your React." Phan Công Thắng | Sciencx - Accessed . https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/
IEEE
" » Build this pagination in your React." Phan Công Thắng | Sciencx [Online]. Available: https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/. [Accessed: ]
rf:citation
» Build this pagination in your React | Phan Công Thắng | Sciencx | https://www.scien.cx/2021/11/07/build-this-pagination-in-your-react/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.