DEV Community

Cover image for Lets make a custom hook for client side Pagination in React
Jyotirmaya Sahu
Jyotirmaya Sahu

Posted on

Lets make a custom hook for client side Pagination in React

Recently while making an application in React, I had to use pagination in one of my lists. So, I decided to keep it simple and came up with an idea of a custom hook.

The custom hook will return a function, to which we can then pass the page number and it will return the first index and last index of the list along with the total number of pages.

Usage:

const [pageNumber, setPageNumber] = useState(1);
const paginator = usePagination(list.length, pageSize); 
//pageSize is the number of items we want to display per page.

const [firstIndex, lastIndex, totalPages] = paginator(pageNumber);
Enter fullscreen mode Exit fullscreen mode

Then we can use this information to slice up our list and implement pagination, we can store the page number in our state and update state based on user interaction.

Now, let's jump into the code that works behind this. The code is fairly simple. In the following snippet, numberOfRecords is the total number of items that the list has, and recordsPerPage is the count of items we want to show per page.

export const usePagination = (numberOfRecords, recordsPerPage) => {
...
}
Enter fullscreen mode Exit fullscreen mode

Now we calculate the following:

  1. noOfWholePages (Number of pages containing items equals to recordsPerPage)
  2. isLastPagePartial (This boolean variable tells if the last page is filled or has less items than recordsPerPage)
  3. noOfRecordsInLastPage (This stores how many items are there in the last page. This will be 0 if isLastPagePartial is false)
  4. noOfPages (The total number of pages)
  const noOfWholePages = Math.trunc(numberOfRecords / recordsPerPage);
  const isLastPagePartial = numberOfRecords % recordsPerPage > 0;
  const noOfRecordsInLastPage = numberOfRecords % recordsPerPage;
  const noOfPages = noOfWholePages + (isLastPagePartial ? 1 : 0);
Enter fullscreen mode Exit fullscreen mode

Now, we need the paginator function to return from the hook. We will use the concept of javascript closures here. So, nothing can be changed in the function other than pageNumber.

  const recordsBuilder = (pageNumber) => {
    const firstIndex = (pageNumber - 1) * recordsPerPage;
    let lastIndex = firstIndex + recordsPerPage - 1;
    if (noOfPages === pageNumber) {
      // Last page
      if (isLastPagePartial) lastIndex = firstIndex + noOfRecordsInLastPage - 1;
    }
    return [firstIndex, lastIndex, noOfPages];
  };
Enter fullscreen mode Exit fullscreen mode

Finally, we return this function from the hook.

return recordsBuilder;
Enter fullscreen mode Exit fullscreen mode

Now let's have a look at the complete code here.

export const usePagination = (numberOfRecords, recordsPerPage) => {
  const noOfWholePages = Math.trunc(numberOfRecords / recordsPerPage);
  const isLastPagePartial = numberOfRecords % recordsPerPage > 0;
  const noOfRecordsInLastPage = numberOfRecords % recordsPerPage;
  const noOfPages = noOfWholePages + (isLastPagePartial ? 1 : 0);
  const recordsBuilder = (pageNumber) => {
    const firstIndex = (pageNumber - 1) * recordsPerPage;
    let lastIndex = firstIndex + recordsPerPage - 1;
    if (noOfPages === pageNumber) {
      // Last page
      if (isLastPagePartial) lastIndex = firstIndex + noOfRecordsInLastPage - 1;
    }
    return [firstIndex, lastIndex, noOfPages];
  };
  return recordsBuilder;
};

Enter fullscreen mode Exit fullscreen mode

I hope this post is helpful. Thank you and stay safe.

Oldest comments (2)

Collapse
 
iamdoctorj profile image
Jyotirmaya Sahu • Edited

Yes correct, but I called it a hook, because I have planned to modify it to handle the page number as well, so it will have some internal state.
Still right now, I agree that it can be a simple function as well.
And the ternary operation. I completely missed it manπŸ˜…. Thanks for the catch.

 
iamdoctorj profile image
Jyotirmaya Sahu

Thanks for the suggestion. Thanks for giving the time to correct me πŸ˜ƒ.