Co to jest stronicowanie (paginacja)?
Paginacja to logika wbudowana w aplikację, która pozwala użytkownikowi przeglądać elementy na liście lub w tabeli w mniejszych kawałkach - podzielonych na strony o określonym rozmiarze.
Dobre, użyteczne stronicowanie powinno pozwalać użytkownikowi wybrać ilość elementów na stronie, zmieniać strony za pomocą przycisków lub wpisując określony numer. Dobra paginacja powinna również informować użytkownika o bieżącej stronie, jej rozmiarze i nie pozwalać na używanie zablokowanych funkcji (np. wyłączanie przycisku "przejdź do pierwszej strony", gdy użytkownik jest na pierwszej stronie itp.)
Jak sobie z tym poradzić za pomocą hooka?
Przede wszystkim - to zależy od źródła danych.
Jeśli stronicowanie jest obsługiwane po stronie backendu - musisz zażądać konkretnej strony, włączając parametry sortowania i inne filtry. Idealnie, backend zwróci liczbę stron, bieżącą stronę, bieżący rozmiar strony i inne informacje, które przekażesz do komponentu paginacji jako propsy.
Jednak często zdarza się, że wszystkie dane pobierane są na raz i paginacja powinna być obsłużona po stronie klienta. Może to zostać obsłużone prostym hookiem:
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; }
Jak to działa?
Hook przyjmuje tylko 3 parametry:
- pageSize - liczba elementów widocznych na stronie jednocześnie
- page - aktualnie wybrany numer strony
- items - dowolna tablica dowolnych obiektów do stronicowania
slice
zwraca podtablicę zaczynającą się od indeksu w pierwszym argumencie i kończącą się na indeksie w drugim argumencie.
Aby wybrać elementy z bieżącej strony, musimy obliczyć indeks początkowy i końcowy.
- Indeks początkowy - pomnóżmy pageSize * page - daje nam to indeks ostatniego elementu, który chcemy pokazać. Jednak chcemy pokazać pageSize elementów, więc cofnijmy indeks o pageSize miejsc, co daje nam pageSize * page - pageSize. Możemy to uprościć do pageSize * (page - 1)
- Indeks końcowy - możemy ponownie użyć pierwszej części poprzedniego równania, więc indeks końcowy będzie po prostu pageSize * page
Krótki opis funkcji slice
znajdziesz w pytaniu rekrutacyjnym slice vs splice - sprawdź to. Możesz także sprawdzić dokumentację slice
na mdn web docs
Rozszerzenie o parametry zapytania
Zwykle chcesz pozwolić użytkownikowi udostępnić jego bieżący stan innym osobom. Może chcieć zapisać zakładkę na konkretnej stronie. Dlatego dobrze jest przechowywać parametry strony i rozmiaru strony w parametrach wyszukiwania URL-a. Poniżej przykład z użyciem hooka useSearchParams
w NextJS:
export 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; }
Gdzie PAGE_SEARCH_PARAM
może być ustawiony jako string page
, a PAGE_SIZE_SEARCH_PARAM
jako pageSize
.