Skip to content

Instantly share code, notes, and snippets.

@crashmax-dev
Created November 21, 2021 12:35
Show Gist options
  • Save crashmax-dev/cc7f5722bc6730447d30ff750d00a888 to your computer and use it in GitHub Desktop.
Save crashmax-dev/cc7f5722bc6730447d30ff750d00a888 to your computer and use it in GitHub Desktop.
react-use-pagination.mjs
// src/getPaginationMeta.ts
var getPreviousEnabled = (currentPage) => currentPage > 0;
var getNextEnabled = (currentPage, totalPages) => currentPage + 1 < totalPages;
var getTotalPages = (totalItems, pageSize) => Math.ceil(totalItems / pageSize);
var getStartIndex = (pageSize, currentPage) => pageSize * currentPage;
var getEndIndex = (pageSize, currentPage, totalItems) => {
const lastPageEndIndex = pageSize * (currentPage + 1);
if (lastPageEndIndex > totalItems) {
return totalItems - 1;
}
return lastPageEndIndex - 1;
};
var limitPageBounds = (totalItems, pageSize) => (page) => Math.min(Math.max(page, 0), getTotalPages(totalItems, pageSize) - 1);
var getPaginationMeta = ({
totalItems,
pageSize,
currentPage
}) => {
const totalPages = getTotalPages(totalItems, pageSize);
return {
totalPages,
startIndex: getStartIndex(pageSize, currentPage),
endIndex: getEndIndex(pageSize, currentPage, totalItems),
previousEnabled: getPreviousEnabled(currentPage),
nextEnabled: getNextEnabled(currentPage, totalPages)
};
};
// src/usePagination.ts
import React from "react";
// src/paginationStateReducer.ts
var getCurrentPageReducer = (rootState) => function currentPageReducer(state, action) {
var page;
if (action.nextPage) {
page = action.nextPage
} else {
page = state
}
switch (action.type) {
case "SET_PAGE":
return limitPageBounds(rootState.totalItems, rootState.pageSize)(action.page);
case "NEXT_PAGE":
return limitPageBounds(rootState.totalItems, rootState.pageSize)(state + 1);
case "PREVIOUS_PAGE":
return limitPageBounds(rootState.totalItems, rootState.pageSize)(state - 1);
case "SET_PAGESIZE":
return limitPageBounds(rootState.totalItems, action.pageSize)(page);
case "SET_TOTALITEMS":
return limitPageBounds(action.totalItems, rootState.pageSize)(page);
default:
return state;
}
};
function totalItemsReducer(state, action) {
switch (action.type) {
case "SET_TOTALITEMS":
return action.totalItems;
default:
return state;
}
}
function pageSizeReducer(state, action) {
switch (action.type) {
case "SET_PAGESIZE":
return action.pageSize;
default:
return state;
}
}
function paginationStateReducer(state, action) {
return {
currentPage: getCurrentPageReducer(state)(state.currentPage, action),
totalItems: totalItemsReducer(state.totalItems, action),
pageSize: pageSizeReducer(state.pageSize, action)
};
}
// src/usePagination.ts
function usePagination({
totalItems = 0,
initialPage = 0,
initialPageSize = 0
} = {}) {
const initialState = {
totalItems,
pageSize: initialPageSize,
currentPage: initialPage
};
const [paginationState, dispatch] = React.useReducer(paginationStateReducer, initialState);
const totalItemsRef = React.useRef(totalItems);
totalItemsRef.current = totalItems;
React.useEffect(() => {
return () => {
if (typeof totalItemsRef.current !== "number" || totalItems === totalItemsRef.current) {
return;
}
dispatch({ type: "SET_TOTALITEMS", totalItems: totalItemsRef.current });
};
}, [totalItems]);
return {
...paginationState,
...React.useMemo(() => getPaginationMeta(paginationState), [paginationState]),
setPage: React.useCallback((page) => {
dispatch({
type: "SET_PAGE",
page
});
}, []),
setNextPage: React.useCallback(() => {
dispatch({ type: "NEXT_PAGE" });
}, []),
setPreviousPage: React.useCallback(() => {
dispatch({ type: "PREVIOUS_PAGE" });
}, []),
setPageSize: React.useCallback((pageSize, nextPage = 0) => {
dispatch({ type: "SET_PAGESIZE", pageSize, nextPage });
}, [])
};
}
// src/Pagination.tsx
function Pagination({
children,
totalItems = 0,
initialPage = 0,
initialPageSize
}) {
return children(usePagination({ totalItems, initialPage, initialPageSize }));
}
Pagination.displayName = "Pagination";
export {
Pagination,
getEndIndex,
getNextEnabled,
getPaginationMeta,
getPreviousEnabled,
getStartIndex,
getTotalPages,
limitPageBounds,
usePagination
};
//# sourceMappingURL=react-use-pagination.mjs.map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment