November 2026 - Data Table Config
One config per Data Table, shared by the server and the hook, plus a URL global filter and a sticky header. Includes breaking changes.
Data Table now describes each table once with createDataTableConfig. The server reads the URL with config.parse, and useDataTable takes the same config, so the two can't drift. This release has breaking changes for server mode, column configs, and table defaults.
Breaking changes
-
One config for the server and the hook.
getDataTableSearchParamsandgetDataTableQueryare removed. Create the config once and parse the search params with it.import { getDataTableSearchParams } from "@/lib/data-table-parsers"; import { createDataTableConfig } from "@/lib/data-table-config"; export const searchParamsCache = createSearchParamsCache( getDataTableSearchParams({ columnConfigs, defaultSorting }), ); export const tasksTableConfig = createDataTableConfig({ columns: columnConfigs, defaultSorting, }); const search = searchParamsCache.parse(searchParams); const query = getDataTableQuery(search, columnConfigs); const query = tasksTableConfig.parse(searchParams);Type the query with
InferDataTableQuery<typeof tasksTableConfig>instead ofDataTableColumnConfigsQuery<typeof columnConfigs>. -
Columns read the config.
getColumnOptionsis removed. Pass the config touseDataTableand it sets each column's filter and sorting. Columns the config doesn't list can't be filtered or sorted.{ accessorKey: "title", meta: { label: "Title" }, ...getColumnOptions(columnConfigs.title), } useDataTable({ config: tasksTableConfig, data, columns, pageCount, }); -
Defaults move to the config. Sorting, page size, page size options, the join operator, and the global filter switch are set on the config.
useDataTablealso takes inline options, likeconfig: { defaultSorting }.useDataTable({ data, columns, initialState: { sorting: [{ id: "createdAt", desc: true }], pagination: { pageIndex: 0, pageSize: 20 }, }, enableGlobalFilter: false, config: { defaultSorting: [{ id: "createdAt", desc: true }], defaultPageSize: 20, enableGlobalFilter: false, }, }); <DataTablePagination table={table} pageSizeOptions={[10, 25, 50]} /> createDataTableConfig({ columns, pageSizeOptions: [10, 25, 50] }); -
idreplacesqueryKeys. Give the config anidto render several tables on one page. It prefixes every URL key, like?tasks.page=2.useDataTable({ queryKeys: { page: "tasksPage", perPage: "tasksPerPage" }, config: createDataTableConfig({ id: "tasks", columns }), }); -
Column config and variant names.
Before After isSortable: falseenableSorting: false"multi-select""select""select"(one option)"select"withmultiple: falsein the column meta"number"withfilter: "range""number", withminandmaxin the column meta for the slider"date"withfilter: "range""date" -
Removed hook props.
throttleMsandautoResetPageIndexare removed.debounceMsonly applies withshallow: falsein server mode, andclearOnDefaultnow defaults totrue. -
Removed helpers.
isRelativeToTodayand theDataTableQueryKeystype are removed.
Data Table
- Global filter in the URL. The global filter is stored as
?search=and reaches the server asquery.globalFilter. PassglobalFilterPlaceholderto either toolbar to show a search input. - Sticky header. Set
stickyHeaderonDataTableto scroll the rows inside the table and keep the header in view. - Escape clears the selection. Pressing Escape inside the table clears the row selection. Call
event.preventDefault()inonEscapeKeyDownto keep it. - Header sort. Picking Asc or Desc in a column header makes it the first sort and keeps the others as tiebreakers, unless multi-sort is off.
- Column ids. Columns defined by
accessorKeyalone now sort and filter through the URL, andDataTableColumnHeaderreads itslabelfrommeta.labelwhen you leave it out. - Pagination. A page size that isn't one of the options still shows in the select, and in client mode, changing rows no longer jumps back to page 1.
- Narrow widths and long labels. Toolbars, filter menus, chips, and headers wrap or truncate instead of overflowing, and labels read correctly in right-to-left layouts.
Data Grid
- Escape.
useDataGridtakesonEscapeKeyDown. Callevent.preventDefault()to keep the selection. - Header sort. Picking Asc or Desc in a column header makes it the first sort, like the Data Table.
- Narrow widths and long labels. The filter, sort, and view menus stay readable at narrow widths and with long labels.
Migrating
- Reinstall the Data Table and Data Grid components you use.
- Replace
getDataTableSearchParamswithcreateDataTableConfig, andgetDataTableQuerywithconfig.parse(searchParams). - Remove
getColumnOptionsfrom your columns and passconfigtouseDataTable. - Move
initialState.sorting, the page size,pageSizeOptions, andenableGlobalFilteronto the config. - Replace
queryKeyswith a configid. - Rename variants and column configs using the table above.
- Remove
throttleMsandautoResetPageIndexfromuseDataTable.