Pagination
Components and hooks for navigating through paged data with cursor-based and offset-based pagination strategies.
Cursor pagination
A pagination component for use with cursor-based pagination. Cursor-based pagination loads data in chunks by using a cursor from the last item on the current page to know where to start the next set. It doesn't let you jump to a specific page or know how many total pages there are, but it's more efficient for large or real-time data sets.
Controlled page size
Root owns the page size when you pass defaultPageSize. When the page size must survive navigation, browser history moves, or a refetch, own it yourself: pass pageSize with onChangePageSize. PageSizeSelect shows the value you pass, so a change from outside the component reaches the select. The demo holds the page size in React state and changes it from a button; a URL search param that a back button rewrites works the same way.
Page size in state: 10
Within a data table
CursorPagination pairs with a DataTable: drive its Buttons and PageSizeSelect from a TanStack Table instance.
Client-paginated: the table holds every row, and the paginatedRowModel slices them. Register rowPaginationFeature and createPaginatedRowModel() with tableFeatures. The table owns the page size, so pass table.state.pagination.pageSize as pageSize and the select follows a setPageSize() call from anywhere. Read getCanPreviousPage() / getCanNextPage() for the buttons and call setPageSize() / setPageIndex(0) when the size changes:
Server / cursor data: the server returns one page at a time, so there is no paginatedRowModel and no total count. Wire Buttons to your fetch's has-next / has-prev and load callbacks, and show the fixed, server-controlled page size with the read-only PageSizeValue instead of PageSizeSelect. The example simulates the server's cursor state with a page index:
See the DataTable pagination recipe for the full table markup.
Composition
Compose the parts of a CursorPagination together to build your own:
API Reference
CursorPagination.Root
The root container for cursor-based pagination. It owns the page size that PageSizeSelect and PageSizeValue read. Pass exactly one of defaultPageSize and pageSize.
All props from the HTML div element, plus:
CursorPagination.Buttons
A pair of previous/next buttons for navigating between pages.
CursorPagination.PageSizeSelect
A select input for changing the number of items per page. Its combobox is named "Items per page" by default, because its visible text is only the current value. Accepts all Select.Trigger props, plus:
CursorPagination.PageSizeValue
Displays the current page size as a read-only value (e.g. "100 per page"). Accepts standard span attributes.
Offset pagination
useOffsetPagination
A headless hook for managing offset-based pagination state. Offset-based pagination lets you jump to a specific page and know the total number of pages.
Page 1 of 15
Own the page
The hook owns the page by default. When the page must survive navigation, browser history moves, or a refetch, own it yourself: pass page with onPageChange. Keep the value where you need it, such as a URL search param. Set resetPageOnListSizeChange to false when a refetch can change the list length. The hook then stays on the current page and clamps it to the new page count instead of returning to page 1. The demo holds the page in React state and starts on page 5; the refetch button shrinks the list to 25 items, and the page clamps to 3.
Page 5 of 15, 150 items
Parameters
Return value
The hook returns an object with the current pagination state and navigation helpers:
getOffsetPaginatedSlice
A utility function to get a paginated slice of a list based on the current offset pagination state. Pair it with useOffsetPagination to render only the current page of items.
- Alpha
- Bravo
- Charlie
Page 1 of 3