@supunlakmal/hooks
Version:
A collection of reusable React hooks
67 lines • 2.9 kB
JavaScript
import { useState, useCallback, useMemo, useEffect } from 'react';
/**
* Custom hook for managing pagination state and controls.
*
* @param {UsePaginationProps} props - Configuration options.
* @param {number} props.totalItems - The total number of items to paginate.
* @param {number} [props.initialPage=1] - The initial page number (1-indexed).
* @param {number} [props.initialItemsPerPage=10] - The initial number of items per page.
* @returns {UsePaginationReturn} An object containing pagination state and control functions.
*/
export const usePagination = ({ totalItems, initialPage = 1, initialItemsPerPage = 10, }) => {
const [currentPage, setCurrentPage] = useState(initialPage);
const [itemsPerPage, setItemsPerPageState] = useState(initialItemsPerPage);
// Calculate total pages
const totalPages = useMemo(() => {
return Math.max(1, Math.ceil(totalItems / itemsPerPage));
}, [totalItems, itemsPerPage]);
// Ensure currentPage stays within valid bounds
const validatedCurrentPage = useMemo(() => {
return Math.max(1, Math.min(currentPage, totalPages));
}, [currentPage, totalPages]);
// Go to a specific page
const goToPage = useCallback((pageNumber) => {
const newPage = Math.max(1, Math.min(pageNumber, totalPages));
setCurrentPage(newPage);
}, [totalPages]);
// Go to the next page
const goToNextPage = useCallback(() => {
goToPage(validatedCurrentPage + 1);
}, [validatedCurrentPage, goToPage]);
// Go to the previous page
const goToPreviousPage = useCallback(() => {
goToPage(validatedCurrentPage - 1);
}, [validatedCurrentPage, goToPage]);
// Set items per page (and reset to page 1)
const setItemsPerPage = useCallback((newItemsPerPage) => {
setItemsPerPageState(Math.max(1, newItemsPerPage));
// Reset to page 1 if current page is out of bounds with new itemsPerPage
setCurrentPage(1);
}, [totalItems]);
// Derived state
const canGoPreviousPage = validatedCurrentPage > 1;
const canGoNextPage = validatedCurrentPage < totalPages;
const startIndex = (validatedCurrentPage - 1) * itemsPerPage;
const endIndex = Math.min(startIndex + itemsPerPage - 1, totalItems - 1);
// Effect to reset page if totalPages decreases below currentPage
// This handles cases where itemsPerPage changes drastically or totalItems decreases
useEffect(() => {
if (currentPage > totalPages) {
setCurrentPage(totalPages);
}
}, [currentPage, totalPages]);
return {
currentPage: validatedCurrentPage,
totalPages,
itemsPerPage,
startIndex,
endIndex,
canGoPreviousPage,
canGoNextPage,
goToPage,
goToNextPage,
goToPreviousPage,
setItemsPerPage,
};
};
//# sourceMappingURL=usePagination.js.map