Skip to content

erictooth/react-use-pagination

Repository files navigation

react-use-pagination

A React hook to help manage pagination state

MIT License Code Style: Prettier 100% coverage

✨ Features

  • 🛠 State-only hook & callbacks, you provide your own UI controls
  • 📦 Compatible with any pagination method like GraphQL Relay Cursor, OData, etc.
  • ⚡️ Works with both server side and client side pagination
  • 🐜 Simple and lightweight — less than 2KB gzipped

Example

import { usePagination } from "react-use-pagination";

function App() {
    const [data] = React.useState([]); // <- your data

    const {
        currentPage,
        totalPages,
        setNextPage,
        setPreviousPage,
        nextEnabled,
        previousEnabled,
        startIndex,
        endIndex,
    } = usePagination({ totalItems: data.length });

    return (
        <div>
            <MyDataTable data={data.slice(startIndex, endIndex)} />

            <button onClick={setPreviousPage} disabled={!previousEnabled}>
                Previous Page
            </button>
            <span>
                Current Page: {currentPage} of {totalPages}
            </span>
            <button onClick={setNextPage} disabled={!nextEnabled}>
                Next Page
            </button>
        </div>
    );
}

Detailed Example

Try out an example on CodeSandbox that showcases full server side pagination

API

const paginationState = usePagination(options);

options

type Options = {
    totalItems: number;
    initialPage?: number; // (default: 0)
    initialPageSize?: number; // (default: 0)
};

paginationState

type PaginationState = {
    // The current page
    currentPage: number;

    // The first index of the page window
    startIndex: number;

    // The last index of the page window
    endIndex: number;

    // Whether the next button should be enabled
    nextEnabled: number;

    // Whether the previous button should be enabled
    previousEnabled: number;

    // The total page size
    pageSize: number;

    // Jump directly to a page
    setPage: (page: number) => void;

    // Jump to the next page
    setNextPage: () => void;

    // Jump to the previous page
    setPreviousPage: () => void;

    // Set the page size
    setPageSize: (pageSize: number, nextPage?: number = 0) => void;
};

Client Side Pagination

startIndex and endIndex can be used to implement client-side pagination. The simplest possible usage is to pass these properties directly to Array.slice:

const [data] = React.useState(["apple", "banana", "cherry"]);
const { startIndex, endIndex } = usePagination({ totalItems: data.length, initialPageSize: 1 });

return (
    <ul>
        {data.slice(startIndex, endIndex + 1).map((item) => (
            <li>{item}</li>
        ))}
    </ul>
);

Server Side Pagination

You can find a complete working example in the Detailed Example section

startIndex and pageSize can be used to implement a standard limit/offset (also known as top/skip) type of pagination:

// Keep track of length separately from data, since data fetcher depends on pagination state
const [length, setLength] = React.useState(0);

// Pagination hook
const { startIndex, pageSize } = usePagination({ totalItems: length, initialPageSize: 1 });

// Fetch Data
const [_, data] = usePromise(
    React.useCallback(
        () => fetchUsers({ offset: startIndex, limit: pageSize }),
        [startIndex, pageSize]
    )
);

// When data changes, update length
React.useEffect(() => {
    setLength(data.length);
}, [data]);

return (
    <ul>
        {data.map((item) => (
            <li>{item}</li>
        ))}
    </ul>
);