Skip to content

Commit

Permalink
Merge pull request #1022 from yaacov/pagination-memo
Browse files Browse the repository at this point in the history
🐞 Remember pagination when data change
  • Loading branch information
yaacov authored Mar 25, 2024
2 parents f45e94e + edcfa0f commit 89e5387
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 966 deletions.
234 changes: 0 additions & 234 deletions packages/common/src/components/Page/__tests__/usePagination.test.tsx

This file was deleted.

39 changes: 9 additions & 30 deletions packages/common/src/components/Page/usePagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,32 @@ import { useMemo, useState } from 'react';

import { PaginationSettings } from './types';

// counting from one seems recommended - zero breaks some cases
const DEFAULT_FIRST_PAGE = 1;
// first option in the default "per page" dropdown
export const DEFAULT_PER_PAGE = 10;

export interface PaginationHookProps<T> {
pagination?: number | 'on' | 'off';
filteredData: T[];
flattenData: T[];
export interface PaginationHookProps {
filteredDataLength: number;
userSettings?: PaginationSettings;
}

export interface PaginationHookResult<T> {
pageData: T[];
showPagination: boolean;
export interface PaginationHookResult {
itemsPerPage: number;
currentPage: number;
setPage: (page: number) => void;
lastPage: number;
setPerPage: (perPage: number) => void;
}

export function usePagination<T>({
pagination,
filteredData,
flattenData,
export function usePagination({
filteredDataLength,
userSettings,
}: PaginationHookProps<T>): PaginationHookResult<T> {
}: PaginationHookProps): PaginationHookResult {
const {
perPage: defaultPerPage = DEFAULT_PER_PAGE,
save: savePerPage = () => undefined,
clear: clearSavedPerPage = () => undefined,
} = userSettings || {};
const [perPage, setPerPage] = useState(defaultPerPage);
const [page, setPage] = useState(DEFAULT_FIRST_PAGE);

const lastPage = Math.ceil(filteredData.length / perPage);
const effectivePage = Math.max(DEFAULT_FIRST_PAGE, Math.min(page, lastPage));
const showPagination =
pagination === 'on' || (typeof pagination === 'number' && flattenData.length > pagination);

const pageData = useMemo(
() => filteredData.slice((effectivePage - 1) * perPage, effectivePage * perPage),
[filteredData, effectivePage, perPage],
);
const lastPage = Math.ceil(filteredDataLength / perPage);

const setPerPageInStateAndSettings = useMemo(
() => (perPage: number) => {
Expand All @@ -60,11 +42,8 @@ export function usePagination<T>({
);

return {
pageData,
showPagination,
itemsPerPage: perPage,
currentPage: effectivePage,
setPage,
lastPage,
setPerPage: setPerPageInStateAndSettings,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,18 @@ export interface StandardPageProps<T> {
*/
pagination?: number | 'on' | 'off';

/**
* page number
*/
page: number;

/**
* Update page number
*
* @param number Update page
*/
setPage: (number) => void;

/**
* Prefix for filters stored in the query params part of the URL.
* By default no prefix is used - the field ID is used directly.
Expand Down Expand Up @@ -258,6 +270,8 @@ export interface StandardPageProps<T> {
* dataSource={[myData, false, null]}
* title="My List"
* fieldsMetadata={myFieldsMetadata}
* page={page}
* setPage={setPage}
* // ...other props
* />
*/
Expand All @@ -273,6 +287,8 @@ export function StandardPage<T>({
customNoResultsFound,
customNoResultsMatchFilter,
pagination = DEFAULT_PER_PAGE,
page,
setPage,
userSettings,
filterPrefix = '',
extraSupportedMatchers,
Expand Down Expand Up @@ -310,13 +326,20 @@ export function StandardPage<T>({
[flatData, selectedFilters, fields, compareFn],
);

const { pageData, showPagination, itemsPerPage, currentPage, setPage, setPerPage } =
usePagination({
pagination,
filteredData,
flattenData: flatData,
userSettings: userSettings?.pagination,
});
const showPagination =
pagination === 'on' || (typeof pagination === 'number' && flatData.length > pagination);

const { itemsPerPage, lastPage, setPerPage } = usePagination({
filteredDataLength: filteredData.length,
userSettings: userSettings?.pagination,
});

const currentPage = Math.min(page, lastPage);

const pageData = useMemo(
() => filteredData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage),
[filteredData, currentPage, itemsPerPage],
);

const errorFetchingData = loaded && error;
const noResults = loaded && !error && flatData.length == 0;
Expand Down
Loading

0 comments on commit 89e5387

Please sign in to comment.