Lets make a custom hook for client side Pagination in React
Tags: reactnative, react, javascript, webdev
Published: 2021-09-06 12:48:49

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:**

```javascript
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);
```

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. 

```javascript
export const usePagination = (numberOfRecords, recordsPerPage) => {
...
}
```

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)
```javascript
  const noOfWholePages = Math.trunc(numberOfRecords / recordsPerPage);
  const isLastPagePartial = numberOfRecords % recordsPerPage > 0;
  const noOfRecordsInLastPage = numberOfRecords % recordsPerPage;
  const noOfPages = noOfWholePages + (isLastPagePartial ? 1 : 0);
```

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.
```javascript
  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];
  };
```

Finally, we return this function from the hook.
```javascript
return recordsBuilder;
```

Now let's have a look at the complete code here.
```javascript
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;
};

```

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