Skip to content

Instantly share code, notes, and snippets.

@HaddadBenjamin
Last active May 21, 2022 18:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HaddadBenjamin/6663177e94df92c3bf4c59f58006bc20 to your computer and use it in GitHub Desktop.
Save HaddadBenjamin/6663177e94df92c3bf4c59f58006bc20 to your computer and use it in GitHub Desktop.
Système pour gérer de la pagination côté client ou serveur
import React, { FC, useEffect, useState } from 'react';
import axios from 'axios';
import Pagination from '../../../shared/components/Pagination/Pagination';
const PAGE_SIZE = 5;
const BackEndPaginationSample : FC = () => {
const [page, setPage] = useState(1);
const [paginatedItems, setPaginatedItems] = useState([]);
useEffect(async () => {
const { data: items } = await axios.get(`https://jsonplaceholder.typicode.com/todos?_start=${(page - 1) * PAGE_SIZE}&_limit=${PAGE_SIZE}`);
setPaginatedItems(items);
}, [page]);
return (
<>
<h2>New pagination back end</h2>
<Pagination
pageSize={PAGE_SIZE}
count={100} /* le nombre total d'éléments doit être renvoyé par l'API */
onPageChange={setPage}
/>
{ JSON.stringify(paginatedItems?.map((e : any) => e.id)) }
</>
);
};
export default BackEndPaginationSample;
const clamp = (number : number, mininium : number, maximum : number) : number => (number < mininium ? mininium : number > maximum ? maximum : number);
export default clamp;
import React, { FC, useState } from 'react';
import Pagination from '../../../shared/components/Pagination/Pagination';
const FrontEndPaginationSample : FC = () => {
const [paginatedItems, setPaginatedItems] = useState<number[]>([]);
return (
<>
<h2>New pagination front end</h2>
<Pagination
items={new Array(100).fill(0).map((e, i) => i + 1)}
pageSize={5}
onPaginatedItemsChange={setPaginatedItems}
/>
{ JSON.stringify(paginatedItems) }
</>
);
};
export default FrontEndPaginationSample;
.container {
display : flex;
align-items: center;
gap : 8px;
}
.page { cursor: pointer;}
.currentPage {
color : red;
}
import React, { useEffect, useState } from 'react';
import cn from 'classnames';
import styles from './Pagination.module.scss';
import clamp from '../../utilities/number/clamp';
const computeButtonsPageRange = (
page : number,
pageSize : number,
lastPage : number,
numberOfPageToDisplay : number) : [number, number] => {
let minimumPageRange = Math.ceil(page - (numberOfPageToDisplay / 2));
let maximumPageRange = minimumPageRange + numberOfPageToDisplay - 1;
const minimumOffset = minimumPageRange < 1 ? minimumPageRange - 1 : 0;
const maximumOfsset = maximumPageRange > lastPage ? maximumPageRange - lastPage : 0;
maximumPageRange = clamp(maximumPageRange - minimumOffset + maximumOfsset, 1, lastPage);
minimumPageRange = minimumPageRange - minimumOffset + maximumOfsset;
minimumPageRange = maximumPageRange - minimumPageRange + 1 < numberOfPageToDisplay ? maximumPageRange - numberOfPageToDisplay + 1 : minimumPageRange;
minimumPageRange = clamp(minimumPageRange, 1, lastPage);
return [minimumPageRange, maximumPageRange];
};
interface Props<TItem>
{
pageSize: number,
numberOfPageToDisplay?: number,
// Props nécéssaires pour gérer une pagination côté client
items? : TItem[],
onPaginatedItemsChange? : (paginatedItems : TItem[]) => void,
// Props nécéssaires pour gérer une pagination côté serveur
count?: number,
onPageChange? : (page : number) => void,
}
const Pagination = <TItem, >({
pageSize = 5,
numberOfPageToDisplay = 6,
items,
onPaginatedItemsChange,
count = 5,
onPageChange,
} : Props<TItem>) => {
const [page, setPage] = useState(1);
const [paginatedItems, setPaginatedItems] = useState(items);
useEffect(() => { setPaginatedItems(items?.slice((page - 1) * pageSize, pageSize * page)); }, [page, pageSize]);
useEffect(() => { onPaginatedItemsChange?.(paginatedItems!); }, [paginatedItems]);
useEffect(() => { onPageChange?.(page); }, [page]);
const lastPage = Math.ceil((items?.length ?? count) / pageSize);
const [minimumPageRange, maximumPageRange] = computeButtonsPageRange(page, pageSize, lastPage, numberOfPageToDisplay);
return (
<div className={styles.container}>
<button onClick={() => setPage(page > 1 ? page - 1 : page)}>{'<'}</button>
{ new Array(maximumPageRange - minimumPageRange + 1).fill(minimumPageRange).map((p, pageIndex) => <div className={cn(styles.page, page === p + pageIndex && styles.currentPage)} key={`page-button-${p + pageIndex}`} onClick={() => setPage(p + pageIndex)}>{p + pageIndex}</div>) }
<button onClick={() => setPage(page < lastPage ? page + 1 : page)}>{'>'}</button>
</div>
);
};
export default Pagination;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment