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
.