How to handle pagination in React using a hook?

Posted by Jakub, 16.06.2024

Stream flowing through the woods - pixel art

What is pagination?

It's very simple - it's a logic embedded to an application, which allows user to browse items on the list or table in smaller chunks.

Nice, useful pagination should allow user to pick page size, change pages, type the page number or jump to first and the last one. Good pagination should also inform user on the current page, page size and don't allow to use blocked features (disable "jump to first page" button when user actually is on the first page etc)

How to handle it using a hook?

First of all - it depends on the source of data.

If the pagination is handled on the backend - you have to request particular page including sort parameters and other filters. Ideally, backend would return number of pages, current page, current page size etc.

However, there're often cases when you fetch all data at once and you want to handle the pagination on the client side. There's a really simple hook for it:

export function usePaginated<T>( pageSize: number = DEFAULT_PAGE_SIZE, page: number = DEFAULT_PAGE, items: T[], ): T[] { const paginated = items.slice(pageSize * (page - 1), pageSize * page); return paginated; }

How does it work?

The hook accepts only 3 parameters:

  • pageSize - number of items visible on the page at once
  • page - currently selected page number
  • items - any array of any objects to be paginated

slice returns subarray starting from index on first agument and ending on index of second argument. To select items from current page, we have to count starting index and ending index.

  • Starting index - let's multiply pageSize * page - it gives us index of the last item we want to show. However, we wan't to show pageSize of items, so let's go back with index by pageSize places, which gives us pageSize * page - pageSize. We can simplify it to pageSize * (page - 1)
  • Ending index - we can reuse first part of previous equation, so the ending index would be just pageSize * page

There's brief explanation of the slice function in the slice vs splice interview question - check it out. You can also check the docs of slice on mdn web docs

Extension with query parameters

Normally, you'd like to let user to share his current state with other people. He might want to save the bookmark on the particular page. Thus, it's nice to keep page and page size params in a search params of the URL. Here's an example of it using useSearchParams hook in NextJS:

xport function usePaginated<T>(items: T[]): T[] { const { queryParams } = useSearchParams(); const pageParam = queryParams.get(SEARCH_PARAMS.PAGE_SEARCH_PARAM); const pageSizeParam = queryParams.get(SEARCH_PARAMS.PAGE_SIZE_SEARCH_PARAM); const page = pageParam ? parseInt(pageParam) : DEFAULT_PAGE; const pageSize = pageSizeParam ? parseInt(pageSizeParam) : DEFAULT_PAGE_SIZE; const paginated = items.slice(pageSize * (page - 1), pageSize * page); return paginated; }

Where PAGE_SEARCH_PARAM might be set to a string page and PAGE_SIZE_SEARCH_PARAM to a pageSize.

You must remember to set these parameters in your pagination component (i.e attach callbacks to buttons etc.)
devFlipCards 2024

Do you accept cookies?

Cookies are small amounts of data saved locally on you device, which helps our website - it saves your settings like theme or language. It helps in adjusting ads and in traffic analysis. By using this site, you consent cookies usage.