Updating your copy
shadcn add copies this block's source into your project — after that,
the code is yours, and upstream releases don't reach it automatically.
This page is the manual update path.
Know what you have
Every release stamps its version into the registry item. When you
install, note the meta.version of
/r/data-table.json somewhere in your project
(a comment, your PR description). The
changelog
lists what changed in each version.
Update recipe
-
Start from a clean branch.
-
Re-run the install command with
--overwrite:bashnpx shadcn@latest add --overwrite <registry-url>/r/data-table.json -
Review the diff. Everything under
components/ui/data-table/is replaced with the new upstream source —git diffshows upstream changes mixed with the loss of any local edits you made. -
Re-apply your local edits on top, or cherry-pick hunks with
git checkout -pagainst the pre-update commit. -
Check the changelog for entries marked as breaking and adjust your usage.
Keep local edits separate
The less you edit the copied files directly — prefer wrapping the table or
using the many render* slots — the closer step 3's diff is to a pure
upstream update.
Localization keys and installed locales
When a release adds localization keys, re-add every locale you installed, otherwise its typecheck fails on the missing keys:
pnpm dlx shadcn@latest add --overwrite <registry-url>/r/data-table-locale-de.json
Do this after re-adding the table, and re-apply any edits you made to a locale file.
Upgrading to 1.0.0
1.0.0 moves the engine to TanStack Table v9 and settles the API. Re-add the block, then:
-
Type columns with
DataTableColumnDef. TanStack v9'sColumnDefneeds a feature-set type parameter; ours supplies it.tsimport type { DataTableColumnDef } from "@/components/ui/data-table" const columns: DataTableColumnDef<Person>[] = [...]DataTableRow,DataTableColumn,DataTableCell, andDataTableHeaderare the matching instance types. Install@tanstack/react-table@^9and@tanstack/match-sorter-utils@^9(the registry item pins both). -
Drop row-model options.
getCoreRowModel,getSortedRowModel, … are no longer accepted; the table wires every row model itself. -
Custom aggregation functions use TanStack v9's
constructAggregationFn({ aggregate })shape. Built-in names ("sum","mean", …) are unchanged. -
Instance APIs follow TanStack v9:
column.pin("start" | "end"),column.getIsPinned()returns"start" | "end",getPrePaginatedRowModel(). Table options andtable.getState()keep theleft/rightpinning shape, andtable.getState().columnSizingInfokeeps its name. Other renames:getLeft*/getRight*aregetStart*/getEnd*(leaf columns, visible cells, header groups, total size),column.getStart("left")andcolumn.getAfter("right")take"start"/"end", andgetPaginationRowModel()isgetPaginatedRowModel(). -
Option and column-def renames reach you too. The column option
sortingFnis nowsortFn.state.columnSizingInfo,initialState.columnSizingInfoandonColumnSizingInfoChangeare nowcolumnResizingandonColumnResizingChange(only the value returned bytable.getState()keeps thecolumnSizingInfoname). -
filterFns,sortingFnsandaggregationFnsoptions are gone. The hook owns the feature set, so pass custom functions inline on the column (filterFn: myFilterFn,sortFn: myCompare,aggregationFn: myAgg). Built-in string names still work. Type inline filter functions with the exportedDataTableFilterFn<TData>. -
Don't destructure row/column/cell methods (
const { getValue } = row); call them on the object. Cell-renderer({ getValue })still works. -
Row data must satisfy TanStack's
RowData(Record<string, any> | Array<any>).unknownis no longer accepted, so use a concrete row type foruseDataTable<TData>andDataTableInstance<TData>.DataTableInstancewith no type argument now defaults toRowData. -
Render contexts are unchanged. Column renderers (
cell,header,footer,aggregatedCell) still receive the enriched instance, so({ table }) => table.getState(),table.dataTableand the table's methods type-check. TanStack v9's own contexts don't includegetState. -
table.optionsis the options object you passed in on the latest render (TanStack v9's React adapter behavior), not TanStack's internally merged options with feature defaults. -
Two small TanStack features are registered by the block. Their types add
dataTableInstanceFeatureanddataTableUiFeaturethrough TanStack'sPlugins/Table_FeatureMap/TableState_FeatureMapinterfaces, scoped to tables built with the block's feature set. Other TanStack tables in your app are unaffected, except ones typedTable<any, …>. -
The component holding the table no longer re-renders on table state changes. If it reads the state while rendering (a selection count, the current density), add
stateSelectorfor what it reads, or wrap that part intable.Subscribe. See State management.
API renames in 1.0.0
| 0.x | 1.0.0 |
|---|---|
table.tableInstance.setDensity(…) (and every setter or action) | table.setDensity(…) |
table.tableInstance.density (and other UI state) | table.getState().density |
table.tableInstance.isLoading (and other options, refs) | table.dataTable.isLoading |
DataTableConfig type | DataTableOptionsResolved (+ DataTableMethods) |
defaultDensity: "compact" | initialState: { density: "compact" } |
density, isFullscreen, showColumnFilters, advancedFilter, globalFilterMode props | state: { … } |
defaultShowColumnFilters, defaultGlobalFilterMode, defaultAdvancedFilter | initialState: { … } |
onEditCellSave / onSaveRow / onCreateRow | onEditingCellSave / onEditingRowSave / onCreatingRowSave |
renderToolbarActions | renderTopToolbarCustomActions |
meta.variant / meta.options | meta.filterVariant / meta.filterSelectOptions |
meta.disableHighlight: true | meta.enableFilterMatchHighlighting: false |
meta.disableColumnActions: true | meta.enableColumnActions: false |
<DataTable pageSizeOptions={…} /> | useDataTable({ pageSizeOptions: … }) |
<DataTable surfaceClassName="…" /> | useDataTable({ slotProps: { surface: { className: "…" } } }) |
renderColumnActionsMenuItems appended after a separator | return <>{internalMenuItems}<DropdownMenuSeparator />{yours}</> |
Edit button next to the renderRowActionMenuItems menu | Edit is in the menu: render internalMenuItems in your items |
sortingFns option | sortFns |