Skip to content

Instantly share code, notes, and snippets.

@halfbug
Created September 29, 2022 12:43
Show Gist options
  • Save halfbug/f7a9dfda0ea0a37e03b3003b04b8d8a5 to your computer and use it in GitHub Desktop.
Save halfbug/f7a9dfda0ea0a37e03b3003b04b8d8a5 to your computer and use it in GitHub Desktop.
usePagination Custom hook to create pagination in any grid.
....
import usePagination from 'hooks/usePagination';
import Pagination from 'react-bootstrap/Pagination';
....
const ProductGrid = ({
...props
}: ProductGridProps) => {
....
const {
screens, breakPoint, pageSize,
totalPages, renderItems, currentPage, setCurrentPage, getPageNumbers,
} = usePagination<IProduct>({
dimensions,
maxrows,
screens: {
xs, sm, md, lg, xl, xxl,
},
items: products || [],
siblingCount: 4,
id,
});
....
return (
....
<Row>
<Col>
{totalPages > 1 && (
<Pagination className={styles.ghop_pagination}>
<Pagination.Prev
className={[(currentPage === 1) ? 'd-none' : '', styles.ghop_pagination_prev].join(' ')}
onClick={() => {
setCurrentPage(
(currentPage > 1) ? currentPage - 1 : currentPage,
);
}}
/>
{getPageNumbers().map((n, index) => (
<Pagination.Item
active={currentPage === n}
onClick={() => {
setCurrentPage(n);
{ (id === 'allproducts') && (paginationScroll()); }
}}
className={currentPage === n
? styles.ghop_pagination_activeItem : styles.ghop_pagination_item}
>
{n}
</Pagination.Item>
))}
<Pagination.Next
className={[(currentPage === totalPages) ? 'd-none' : '', styles.ghop_pagination_next].join(' ')}
onClick={() => {
setCurrentPage(
(currentPage >= 1 && currentPage < totalPages) ? currentPage + 1 : currentPage,
);
{ (id === 'allproducts') && (paginationScroll()); }
}}
/>
</Pagination>
)}
</Col>
</Row>
..):
}
import React, { useEffect, useCallback, useState } from 'react';
import useDimensions from './useDimentions';
export type ScreensProps= { [key: string]: number } & {
xs?: number,
sm?: number,
md?: number,
lg?: number,
xl?: number,
xxl?: number,
}
type PaginationProps<T> = {
dimensions : any;
maxrows: number,
screens: ScreensProps
items: T[],
siblingCount: number,
id?: string,
// currentPage: number,
}
const usePagination = <T extends {}>({
maxrows, screens, items, dimensions, siblingCount, id,
}:PaginationProps<T>) => {
// const [ref, dimensions] = useDimensions();
const [breakPoint, setBreakPoint] = useState<string>('sm');
const [pageSize, setPageSize] = useState<number>(6);
const [totalPages, setTotalPages] = useState<number>(1);
const [renderItems, setRenderItems] = useState<typeof items | undefined>(undefined);
const [currentPage, setCurrentPage] = useState<number>(1);
useEffect(() => {
if (dimensions.width && items?.length > 0) {
setVals(dimensions.width);
getPageNumbers();
}
}, [dimensions, items, currentPage]);
useEffect(() => {
if (items?.length > 0 && currentPage !== 1 && id === 'shoppedby') {
setCurrentPage(1);
}
}, [items]);
const breakpoints: { [char: string]: number } = {
// xs: 0,
// sm: 576,
md: 768,
lg: 992,
xl: 1200,
xxl: 1400,
};
const setVals = (currentWidth: number) => {
let bPoint = 'sm';
for (const key in breakpoints) {
if (breakpoints[key] < currentWidth) { bPoint = key; } else { break; }
}
// bPoint = (bPoint === xs )
setBreakPoint(bPoint);
const pagesize = (12 / screens[bPoint]) * maxrows;
setPageSize(pagesize);
const totalpages = Math.ceil((items.length) / pagesize);
setTotalPages(totalpages);
if (totalpages === 1) {
setCurrentPage(1);
}
const start = (currentPage > 1)
? (currentPage - 1) * pagesize : currentPage - 1;
const end = (currentPage > 0)
? currentPage * pagesize : pagesize;
setRenderItems(items.slice(start, end));
};
const range = (start: number, end: number) => Array(end - start + 1)
.fill(0).map((_, idx) => start + idx);
const getPageNumbers = useCallback(() => {
let start : number = 1;
let end : number = siblingCount;
const pageLeft = totalPages - currentPage;
if (currentPage - 1 > 0 && pageLeft >= siblingCount - 2) {
start = currentPage - 1 > 0 ? currentPage - 1 : 1;
end = start + (siblingCount - 1);
} else if (totalPages < siblingCount && totalPages > 1) {
end = totalPages;
} else if (pageLeft < siblingCount && totalPages > 1) {
start = totalPages - (siblingCount - 1);
end = totalPages;
}
return range(start, end);
}, [currentPage, totalPages]);
return {
breakPoint,
pageSize,
totalPages,
renderItems,
currentPage,
setCurrentPage,
getPageNumbers,
screens,
};
};
export default usePagination;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment