Skip to content
Redpanda UI
Esc
↑↓navigate↵open⌘Jpreview
On this page

useDataTableSearchParams

Sync TanStack Table V9 state through route-owned, validated TanStack Router search params.

Installation

npx shadcn@latest add @redpanda/use-data-table-search-params
pnpm dlx shadcn@latest add @redpanda/use-data-table-search-params
yarn dlx shadcn@latest add @redpanda/use-data-table-search-params
bunx shadcn@latest add @redpanda/use-data-table-search-params
nubx shadcn@latest add @redpanda/use-data-table-search-params
aube dlx shadcn@latest add @redpanda/use-data-table-search-params

useDataTableSearchParams maps pagination, sorting, optional column filters, and optional global search to shareable URL state. The route validates search params; a provider adapts the typed route hooks to the reusable registry hook. Navigation merges previous search state and uses replace: true.

Route setup

import { createRoute } from "@tanstack/react-router"
import {
  DataTableSearchParamsProvider,
  validateDataTableSearchParams,
} from "@/hooks/use-data-table-search-params"

export const usersRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/users",
  validateSearch: validateDataTableSearchParams,
  component: UsersRoute,
})

function UsersRoute() {
  const search = usersRoute.useSearch()
  const navigate = usersRoute.useNavigate()

  return (
    <DataTableSearchParamsProvider search={search} navigate={navigate}>
      <UsersTable />
    </DataTableSearchParamsProvider>
  )
}

Keep validateSearch on the route that owns the table. Use that route’s useSearch and useNavigate helpers so TanStack Router infers types without casts or strict: false access.

Table setup

import { DataTable } from "@/components/redpanda-ui/data-table"
import { useDataTableSearchParams } from "@/hooks/use-data-table-search-params"

function UsersTable() {
  const {
    pagination,
    onPaginationChange,
    sorting,
    onSortingChange,
    globalFilter,
    onGlobalFilterChange,
  } = useDataTableSearchParams({ syncGlobalFilter: true })

  return (
    <DataTable
      columns={columns}
      data={data}
      tableOptions={{
        state: { pagination, sorting, globalFilter },
        onPaginationChange,
        onSortingChange,
        onGlobalFilterChange,
      }}
    />
  )
}

Multiple tables

Prefix keys when several tables share a route.

import { createDataTableSearchParamsValidator } from "@/hooks/use-data-table-search-params"

const validateSearch = createDataTableSearchParamsValidator({
  prefixes: ["users", "teams"],
})

const usersState = useDataTableSearchParams({ paramPrefix: "users" })
const teamsState = useDataTableSearchParams({ paramPrefix: "teams" })

This produces keys such as users_page, users_pageSize, users_globalFilter, and teams_sort. Declare every prefix in the route validator so similarly named, unrelated route params remain untouched.

First-page resets

Sorting, column-filter, global-filter, and page-size changes reset pagination to page 1 by default. The reset is merged into the same TanStack Router navigation, so the URL never exposes a transient stale page. Set resetPageOnStateChange: false only when the backing data source deliberately preserves page position.

API

validateDataTableSearchParams(search)

Use as TanStack Router’s validateSearch. It normalizes positive page values, validates column.direction sorting segments, filter JSON, and string global filters, rejects malformed table state, and preserves unrelated route search params.

createDataTableSearchParamsValidator({ prefixes })

Create a validateSearch function for routes with prefixed table state. Only unprefixed table keys and keys matching the declared prefixes are validated; all other search params pass through unchanged.

DataTableSearchParamsProvider

Prop Type Description
search DataTableSearchParams Value returned by the owning route’s useSearch.
navigate DataTableSearchParamsNavigate Typed adapter around the owning route’s useNavigate.
children ReactNode Tables that consume URL state.

useDataTableSearchParams(options?)

Option Type Default Description
syncPagination boolean true Sync pagination.
syncSorting boolean true Sync sorting.
syncFilters boolean false Sync column filters.
syncGlobalFilter boolean false Sync the V9 global-filter slice.
paramPrefix string — Namespace keys for one table.
defaultPagination PaginationState { pageIndex: 0, pageSize: 10 } State used when the URL omits pagination.
defaultSorting SortingState [] State used when the URL omits sorting.
defaultGlobalFilter string "" State used when the URL omits global search.
resetPageOnStateChange boolean true Reset to page 1 atomically when sorting, filtering, global search, or page size changes.

Returns TanStack Table-compatible state slices and onChange handlers. Pass them through DataTable’s tableOptions.

For token APIs that cannot express offsets, use useTokenPagination.

Last updated on October 7, 2026

Was this page helpful?