Pagination & URL State (nuqs)
Overview
Our data tables use URL-synchronized state via nuqs. Pagination should be stable: selecting rows or toggling non-paging controls must not reset the current page to 1. This guide explains:- How pagination parameters are modeled
- Which URL params trigger a page reset
- The
OMIT_FIELDS
list used to prevent unwanted resets - Practical recommendations when adding new URL params
Key URL Parameters
page
: current page (1-based)size
: page sizesort
: sort field keyasc
: sort direction (boolean)filter
: whether filtering UI is enabled (boolean)- Additional dynamic filter params (e.g.,
doc_date
,status
, etc.) - Selection and UI-only params (e.g.,
selected
)
Page Reset Rules
Changing actual filter values should reset to page 1 so users see results from the beginning. However, changes to purely presentational or ephemeral state (like selection) must not trigger a reset. We implement this using an omit list during change detection.OMIT_FIELDS
Source of truth in the webapp utility:page
to the default.
Where Reset Happens
The reset to page 1 is applied inprocessSearchParams
when a meaningful change is detected:
useQueryFiltersSync
resets page
when any filter group (not omitted) changes, using a debounced effect to avoid jitter during typing:
What Should Not Reset Pagination
The following changes must not reset the page:- Row selection changes:
selected
- Sorting toggles:
sort
,asc
- Pagination controls themselves:
page
,size
- View toggles/tabs:
tab
- UI-only flags that don’t change the dataset shape
OMIT_FIELDS
or otherwise do not affect the reset logic.
What Should Reset Pagination
Any change that alters the dataset shape/order enough that page N might no longer contain the same items, for example:- Adding/removing/changing filter values (e.g.,
doc_date
,status
) - Toggling
filter
that enables filter mode and reveals active filters - Changing object scoping parameters
OMIT_FIELDS
so that the system resets to page 1.
Best Practices When Adding Params
- Classify the parameter:
- Data-affecting (should reset) vs. UI-only/ephemeral (should not reset)
- If it should not reset, add its key to
OMIT_FIELDS
insearch-params-utils.ts
. - Keep pagination stable on selection and sort changes.
- Debounce page resets on filter edits to avoid flicker.
- Keep URL key mapping consistent (see
search-params-config
forpageSize
⇄size
).
Example: Row Selection Should Not Reset
In AR Reconciliation, selecting a row updates theselected
query param. Because selected
is listed in OMIT_FIELDS
, changing selection will not reset page
.
Troubleshooting
- Pagination resets unexpectedly: Verify the param is in
OMIT_FIELDS
if it is UI-only. - Page doesn’t reset when filters change: Ensure those filter keys are NOT in
OMIT_FIELDS
and that they flow throughprocessSearchParams
. - Jumping during typing: Confirm debounce is applied in
useQueryFiltersSync
.
By following these rules and maintaining
OMIT_FIELDS
, pagination remains predictable while filters and controls work as expected.