Pagination
How page and per_page are mirrored into params, and how filter changes reset the page.
Pagination is built in. Unless you turn it off, params always includes the page
and per-page values, mirrored straight from the URL:
const { params } = useFilters(configs);
// params = { ...filters, page: 1, per_page: 10 }The keys are yours to name (they default to page / per_page), and they're the
same in the URL and in params: there's no separate mapping to maintain. You
set them once with createFilters:
export const { useFilters } = createFilters({
pagination: { pageKey: 'page', perPageKey: 'page_size', defaultPerPage: 25 }
});
// URL: ?page=2&page_size=25 → params: { page, page_size }Reading and setting the page
The page and per-page values are plain keys on params. You drive them however
your pagination UI works (nuqs directly, or your own state) and spread them into
your query. useFilters doesn't render pagination controls; it just keeps the
values in the URL and in params.
Resetting on filter change
When a filter changes, the old page of results no longer applies: page 7 of an unfiltered list isn't page 7 of the filtered one. So by default, changing any filter resets the page to its first value:
// User is on page 5, then edits a filter → params.page becomes 1 again.If your pagination is driven entirely outside the hook and it should never touch the page param, opt out, for the whole app or one screen:
createFilters({ pagination: { resetPageOnFilterChange: false } });
// or per call:
useFilters(configs, { pagination: { resetPageOnFilterChange: false } });First page and 0-indexed APIs
firstPage is the number your first page counts from: the value when the URL has
none, what a reset writes, and the base your backend expects. It defaults to 1;
set it to 0 for a 0-indexed API:
createFilters({ pagination: { firstPage: 0 } });
// The first page is ?page=0, in both the URL and params.This is also how you drive an offset/limit backend directly, with no
conversion at all. Name the keys to match and let firstPage: 0 be the starting
offset:
createFilters({ pagination: { pageKey: 'offset', perPageKey: 'limit', firstPage: 0 } });
// params: { offset, limit, ...filters }; increment `offset` by `limit` yourself
// (e.g. setFilter('offset', offset + limit)) to page forward.pageKey / perPageKey don't have to mean "page number"; they're just the two
pagination values useFilters mirrors into params and resets on filter change.
Only reach for a page-number UI (1, 2, 3…) converting to offset/limit at the fetch
call if your UI specifically wants page numbers; if it doesn't, drive the
backend's own values directly instead.
Turning pagination off
Pass pagination: false for a call that has no pages (a settings filter, a
faceted sidebar with infinite scroll). params then contains only your filters,
with no page keys, and filter changes don't reset anything.
Full option details are in the createFilters reference.