Capítulo 42 de 54
pagination state ({ pageIndex, pageSize }) is identical whether pagination is client-side (paginatedRowModel) or server-side (manualPagination: true + rowCount/pageCount) — the same button APIs and state work either way, so switching between them later mostly means swapping data/row-model wiring, not rewriting UI.
rowPaginationFeature + paginatedRowModel: createPaginatedRowModel(), data holds every row, the table slices pages itself. Use when the browser can hold the complete dataset (row count alone isn't the deciding factor — see Client-Side vs Server-Side Guide).manualPagination: true) the paginated row model; data is assumed already paginated. Must supply either rowCount (table derives pageCount from rowCount/pageSize) or pageCount directly. Pass pageCount: -1 when the total is unknown (cursor pagination): getCanNextPage() then always returns true (can't detect the end), getCanPreviousPage() still works off pageIndex, and getCanLastPage() returns false (no finite last page to jump to) — the Next button should instead derive its enabled state from whether more data is actually available (e.g. a cached next cursor page or a hasNextPage flag from the server response).pagination, sorting, globalFilter, ...) in the query key; return rows + rowCount (or, for cursor APIs, rows + nextCursor/hasNextPage); pass manualPagination: true (+ manualSorting/manualFiltering as applicable) and onPaginationChange. Offset-style (useQuery) gives full page-number navigation since the total is known; cursor-style (useInfiniteQuery with pageCount: -1) trades that for cheaper "no full count needed" pagination, and nextPage() must first ensure the next cursor page is fetched/cached before calling table.nextPage().table.state.pagination (reactive) / table.atoms.pagination.get() (snapshot). Ownership: external atom via atoms: { pagination: atom } (v9-recommended, especially for a query-key-driving slice) or classic state.pagination + onPaginationChange, or initialState.pagination alone for non-controlled starting values. Never combine more than one ownership channel for the same slice — a controlled value (atoms/state) always overrides initialState.pageIndex resets to 0 by default whenever a client-side row model that feeds pagination recomputes (data/filter/sort/group changes) — automatically disabled once manualPagination: true, or override with autoResetPageIndex/global autoResetAll. Under manual pagination with a relevant row model omitted, changing that controlled state does not trigger the reset even if autoResetPageIndex is true — reset pageIndex by hand in the change handler (this is the same caveat covered in the Client-Side vs Server-Side and Column Filtering guides). A common deliberate autoResetPageIndex: false use case: inline data editing, where every edit updating data would otherwise snap the user back to page one — pair with autoResetExpanded: false if expanding is also in play.getCanPreviousPage(), getCanNextPage(), getCanLastPage(), previousPage(), nextPage(), firstPage(), lastPage(), setPageIndex(n), resetPageIndex(), setPageSize(n), resetPageSize(), setPagination(...), resetPagination().getPageCount(), getRowCount().const features = tableFeatures({ rowPaginationFeature, paginatedRowModel: createPaginatedRowModel() })
// server-side, offset style
const dataQuery = useQuery({
queryKey: ['people', pagination, sorting],
queryFn: () => fetchPeople({ pagination, sorting }),
placeholderData: keepPreviousData,
})
const table = useTable({
features, columns, data: dataQuery.data?.rows ?? [], rowCount: dataQuery.data?.rowCount,
state: { pagination, sorting }, onPaginationChange: setPagination, manualPagination: true, manualSorting: true,
})
<button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>{'<'}</button>
<button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>{'>'}</button>
useTable options, not the render code.pageCount: -1), drive the Next button from actual data availability, not getCanNextPage() — it always returns true in that mode.autoResetPageIndex: false is required for any table that supports inline editing without jarring page jumps.pagination through more than one of atoms/state/initialState at once.manual* pattern.