Shadcn React Table

Search documentation

Search the docs

Table instance

useDataTable returns the standard TanStack table instance with three additions: the table's UI state in table.getState() (density, editing, filter modes…), methods to change it on table itself, and the resolved options and DOM refs on table.dataTable.

tsx
table.beginCreate() // open the create-row form
table.setDensity("compact")
const density = table.getState().density
const isLoading = table.dataTable.isLoading
table.dataTable.refs.searchInputRef.current?.focus()

Methods

MethodTypeDescription
setDensity#React.Dispatch<React.SetStateAction<Density>>Updates `density`.
setIsFullscreen#React.Dispatch<React.SetStateAction<boolean>>Updates `isFullscreen`.
setShowColumnFilters#React.Dispatch<React.SetStateAction<boolean>>Updates `showColumnFilters`.
setShowGlobalFilter#React.Dispatch<React.SetStateAction<boolean>>Open or close the global search box.
setColumnFilterMode#(columnId: string, mode: FilterMode) => voidSwitch a column's filter mode (resets the value when it becomes invalid).
setGlobalFilterMode#(mode: GlobalFilterMode) => voidUpdates `globalFilterMode`.
setAdvancedFilter#React.Dispatch<React.SetStateAction<AdvancedFilterGroup>>Updates `advancedFilter`.
setShowAdvancedFilterPanel#React.Dispatch<React.SetStateAction<boolean>>Updates `showAdvancedFilterPanel`.
autoSizeColumn#(columnId: string) => voidResize a single column to fit its widest visible value (header + data).
autoSizeAllColumns#() => voidAuto-size every resizable visible column.
setEditingCell#React.Dispatch<React.SetStateAction<EditingCell | null>>Updates `editingCell`.
setRowDraftValue#(columnId: string, value: unknown) => voidUpdates `rowDraftValue`.
beginRowEdit#(row: DataTableRow<TData>) => voidEnter row/modal editing for a row, seeding the draft from its values.
beginCreate#() => voidOpen the create form, seeding the draft from `createRowDefaults`.
cancelEdit#() => voidExit any editing/creating state, discarding the draft.

table.dataTable

MemberTypeDescription
localization#DataTableLocalizationText for every label, message and screen-reader string. Partial: missing keys fall back to English (or to `DataTableConfigProvider`). Install a locale item for a full language.
icons#DataTableIconsOverride any subset of the table's icons.
filterFns#Record<string, DataTableFilterFn<TData>>The consumer's own filter functions, by name.
columnFilterModeOptions#FilterMode[] | undefinedTable-wide filter-mode menu modes, if restricted.
globalFilterModeOptions#GlobalFilterMode[]The global search mode menu's modes.
enableGlobalFilter#booleanShow the expandable global search in the toolbar. Default true.
enableGlobalFilterModes#booleanShow the global search mode menu (fuzzy/contains/…). Default true.
enableAdvancedFilter#booleanCompound AND/OR filter panel (independent of, and additive to, the per-column filters and global search).
isLoading#booleanShow the loading affordances (progress bar; skeletons when empty; a dimming overlay over existing rows). Toggle each independently below.
isSaving#booleanShow the progress bar for an in-flight save/mutation. Defaults the progress bar on without replacing rows with skeletons.
showProgressBars#booleanShow the top progress bar. Default: `isLoading || isSaving`.
showSkeletons#booleanShow skeleton rows while the body is empty. Default: `isLoading`. Passing `true` also covers rows already shown with skeletons (e.g. while refetching), instead of dimming them.
showSkeletonsOverRows#booleanWhether skeletons also cover rows already shown (`showSkeletons: true` was passed explicitly).
showLoadingOverlay#booleanDim existing rows with an overlay while loading. Default: `isLoading`.
enableFacetedValues#booleanCompute faceted unique values / min-max (auto select options + range bounds). Default true; disable to skip the faceted row models.
enableColumnActions#booleanShows the column-actions menu in each header (sort, filter, pin, hide, group…). Default `true`.
enableColumnFilters#booleanWhether per-column filters are on.
enableColumnFilterModes#booleanShow the filter-mode menu adornment on filter fields. Default true.
enableFilterMatchHighlighting#booleanHighlight matched substrings in cells. Default true.
enableColumnOrdering#booleanDrag-and-drop column reordering (adds a grip to each header).
enableColumnPinning#booleanColumn pinning (left/right) via the column-actions menu + sticky columns.
enableColumnResizing#booleanColumn resizing via an edge drag handle.
layoutMode#LayoutModeHow the table sizes its columns (see {@link LayoutMode}).
enableColumnAutosize#booleanDouble-clicking a column's resize handle auto-sizes it to fit its widest value. Defaults to `enableColumnResizing`. When off, double-click resets the column to its default size instead.
enableRowOrdering#booleanDrag-and-drop row reordering (adds a drag-handle column).
enableRowPinning#booleanRow pinning (top) via a pin toggle in the row-number column.
enableRowNumbers#booleanAdds a leading row-number column.
rowNumberMode#"static" | "original""static" tracks the current view (page-aware); "original" uses source index.
onRowOrderChange?#(activeRowId: string, overRowId: string) => voidCalled on a row drag-and-drop reorder; the consumer reorders its data.
enableGrouping#booleanRow grouping (group-by menu + drop-to-group zone + aggregated group rows).
enableExpanding#booleanRow expansion (tree sub-rows and/or detail panels). Auto-on with grouping or when `renderDetailPanel`/`getSubRows` is provided.
enableStickyFooter#booleanPin the footer (aggregation/footer cells) to the bottom of the surface. Default false.
rowPinningDisplayMode#RowPinningDisplayModeWhere pinned rows show and how rows get pinned.
enableRowDragging#booleanWhether rows have a drag handle for moving them out of the table.
onRowDragEnd?#(props: { row: DataTableRow<TData> table: DataTableInstance<TData> over: RowDropTarget }) => voidCalled when a row is dropped on another table or a drop zone in the same `DataTableDndProvider`. Move the row in your data.
enableTableHead#booleanWhether the header rows render.
enableTableFooter#booleanWhether the footer rows render (when columns define footers).
enableExpandAll#booleanWhether the expand column's header toggles every row.
renderDetailPanel?#(props: { row: DataTableRow<TData> table: DataTableInstance<TData> }) => React.ReactNodeRender an expanding detail panel for each row.
enableEditing#booleanWhether editing is on (a per-row `enableEditing` function counts).
displayColumnDefOptions#| Partial< Record<DisplayColumnId, Partial<DataTableColumnDef<TData, unknown>>> > | undefinedOverrides for the columns the table adds itself, by id. A new object re-renders the rows, so memoize it when you pass functions.
defaultDisplayColumn#Partial<DataTableColumnDef<TData, unknown>> | undefinedOverrides for every column the table adds itself.
getCanEditRow#(row: DataTableRow<TData>) => booleanWhether a row can be edited: the `enableEditing` function's answer, or `enableEditing` itself.
editDisplayMode#EditDisplayModeHow edits are surfaced. Default "cell".
createDisplayMode#CreateDisplayModeHow the create form is surfaced, independent of `editDisplayMode`: `"modal"` (dialog, default), `"row"` (an inline editable row at the top of the table), or `"custom"` (you render it from `isCreating` + `rowDraft`).
cancelEditing#() => voidCancel as the user does: calls `onEditingRowCancel` / `onCreatingRowCancel`, then `cancelEdit`.
onEditingRowCancel?#(props: { row: DataTableRow<TData> table: DataTableInstance<TData> }) => voidCalled when the user cancels a row edit (Cancel, closing the dialog).
onCreatingRowCancel?#(props: { table: DataTableInstance<TData> }) => voidCalled when the user cancels the create form.
renderEditRowDialogContent?#( props: EditDialogContentProps<TData> & { row: DataTableRow<TData> } ) => React.ReactNodeReplace the edit dialog's content. You get the built-in fields as `internalEditComponents`, plus `save()` / `cancel()`.
renderCreateRowDialogContent?#( props: EditDialogContentProps<TData> ) => React.ReactNodeReplace the create dialog's content (same props, without `row`).
positionCreatingRow#"top" | "bottom" | numberWhere the inline create row (`createDisplayMode: "row"`) appears: `"top"` (default), `"bottom"`, or a row index on the current page to insert it before (with row virtualization an index means `"top"`).
enableClickToCopy#ClickToCopyOption<TData>Copy cells on click (`true`), from the cell menu (`"context-menu"`), or decide per cell with a function. Per-column override via meta.
enableCellActions#boolean | ((cell: DataTableCell<TData, unknown>) => boolean)A right-click menu on each cell with built-in Copy (when click-to-copy is on) and Edit (when the cell is editable) items, or a function deciding per cell. `renderCellActionMenuItems` customizes it. Default false.
onEditingCellSave?#(props: { row: DataTableRow<TData> column: DataTableColumn<TData, unknown> value: unknown table: DataTableInstance<TData> }) => voidCalled when a cell edit is committed (cell and table editing) with the new `value`. Persist it; the table does not change `data` itself.
onEditingRowSave?#(props: { row: DataTableRow<TData> values: Record<string, unknown> table: DataTableInstance<TData> exit: () => void }) => voidCalled when a row edit is saved (row and modal editing) with the edited `values`. Call `exit()` to leave editing, e.g. after the save succeeds.
onCreatingRowSave?#(props: { values: Record<string, unknown> table: DataTableInstance<TData> exit: () => void }) => voidCalled when the new-row editor is saved with the row's `values`. Call `exit()` to close it.
renderRowActions?#(props: { row: DataTableRow<TData> table: DataTableInstance<TData> }) => React.ReactNodeContent of the row-actions column, replacing the default edit and menu buttons.
renderCellActionMenuItems?#(props: { cell: DataTableCell<TData, unknown> row: DataTableRow<TData> table: DataTableInstance<TData> /** The built-in items (Copy, Edit) the menu shows for this cell. */ internalMenuItems: React.ReactNode closeMenu: () => void }) => React.ReactNodeThe contents of the right-click menu on each cell (turns the menu on). Include `internalMenuItems` to keep the built-in Copy / Edit items.
renderRowActionMenuItems?#(props: { row: DataTableRow<TData> table: DataTableInstance<TData> /** The built-in items (Edit, when the row can be edited). */ internalMenuItems: React.ReactNode closeMenu: () => void }) => React.ReactNodeRender a kebab menu in the row-actions column. Returns the menu items (e.g. `<DropdownMenuItem>`); injects the actions column automatically. While editing is on, the Edit action moves into this menu: include `internalMenuItems` to keep it.
renderColumnActionsMenuItems?#(props: { column: DataTableColumn<TData, unknown> table: DataTableInstance<TData> /** The built-in items (sort, filter, hide, group, pin). */ internalMenuItems: React.ReactNode closeMenu: () => void }) => React.ReactNodeThe contents of every column-actions menu. Return your items (e.g. `<DropdownMenuItem>`) with `internalMenuItems` where the built-in ones should go, or leave it out to replace them.
renderColumnFilterModeMenuItems?#(props: { column: DataTableColumn<TData, unknown> modes: FilterMode[] currentMode: FilterMode onSelect: (mode: FilterMode) => void table: DataTableInstance<TData> }) => React.ReactNodeReplace the radio items in a column's filter-mode menu. Render your own items and call `onSelect(mode)` to switch; `modes` is the allowed set.
renderGlobalFilterModeMenuItems?#(props: { modes: GlobalFilterMode[] currentMode: GlobalFilterMode onSelect: (mode: GlobalFilterMode) => void table: DataTableInstance<TData> }) => React.ReactNodeReplace the radio items in the global-search mode menu. Render your own items and call `onSelect(mode)` to switch; `modes` is the allowed set.
onRowClick?#(props: RowEvent<TData>) => voidFired when a body row is clicked / double-clicked.
onRowDoubleClick?#(props: RowEvent<TData>) => voidCalled when a row is double-clicked. Double-clicks on controls inside the row (edit, expand, pin…) are ignored.
onCellClick?#(props: CellEvent<TData>) => voidFired when a body cell is clicked / double-clicked.
onCellDoubleClick?#(props: CellEvent<TData>) => voidCalled when a cell is double-clicked. Double-clicks on controls inside the cell are ignored.
refs#DataTableRefsDOM refs to the table's structural elements (populated after mount).
enableRowVirtualization#booleanVirtualize body rows for large datasets (recommended past ~100 rows). The table surface becomes the scroll container — give it a bounded height via `className`/`style` (defaults to `max-h-[600px]`). Rows can still be dragged: the dragged row stays rendered while the drag scrolls.
enableColumnVirtualization#booleanVirtualize columns for very wide tables. Applies fixed column widths; works with column pinning (pinned columns stay rendered), column ordering and grouped headers.
estimateRowHeight#numberEstimated row height (px) for the virtualizer. Default 52.
virtualOverscan#numberExtra rows rendered above/below the viewport. Default 8.
rowHeight?#numberFlat height (px) applied to every row.
getRowHeight?#(row: DataTableRow<TData>) => number | "auto" | nullPer-row height: a px number, `"auto"` (wrap + grow), or `null` for default.
rowVirtualizerOptions?#RowVirtualizerOptions<TData>Partial `@tanstack/react-virtual` options merged into the row virtualizer (overrides the built-in `count`/`estimateSize`/`overscan`/`measureElement`). A `rangeExtractor` picks the rendered rows; a row being dragged is added to its result. Accepts an object or a `({ table }) => options` function.
columnVirtualizerOptions?#ColumnVirtualizerOptions<TData>Partial `@tanstack/react-virtual` options merged into the column virtualizer. Accepts an object or a `({ table }) => options` function.
rowVirtualizerInstanceRef?#React.RefObject<DataTableRowVirtualizer | null>Ref populated with the row `Virtualizer` instance for imperative control (e.g. `scrollToIndex`). Only set when `enableRowVirtualization`.
columnVirtualizerInstanceRef?#React.RefObject<DataTableColumnVirtualizer | null>Ref populated with the column `Virtualizer` instance. Only set when `enableColumnVirtualization`.
enableStickyHeader#booleanPin the header rows to the top of the scrollable surface. Also gives the surface a default viewport-bound max-height (`clamp(350px, 100dvh - 200px, 9999px)`) so tall content scrolls internally; override the bound with `slotProps.surface`. Default true.
enablePagination#booleanSplits rows into pages with pagination controls. Default `true`; turn it off for virtualization or infinite scroll.
enableInfiniteScroll#booleanLoad more rows as the user scrolls near the bottom (auto-hides the pager).
onLoadMore?#() => voidCalled when the sentinel nears the viewport and more rows can be loaded.
hasNextPage#booleanConsumer flag: more rows exist to load.
isFetchingNextPage#booleanConsumer flag: a load is currently in flight.
infiniteScrollThreshold#numberDistance (px) from the bottom at which to prefetch.
positionPagination#"top" | "bottom" | "both" | "none"Where the pagination controls render. Default "bottom". "none" keeps pagination active but hides the controls.
paginationDisplayMode#PaginationDisplayModePagination control style: `"default"` (range label + first/prev/next/last buttons), `"pages"` (numbered page buttons), or `"custom"` (render your own via `renderBottomToolbarCustomActions`). Default "default".
pageSizeOptions#number[]Choices in the rows-per-page select.
slotProps#DataTableSlots<TData> | undefinedProps for the table's parts; see the `slotProps` option.
columnFilterDisplayMode#ColumnFilterDisplayModeWhere column filter inputs live: `"subheader"` (a filter row under the header, default), `"popover"` (per-column popovers opened from the column header), or `"custom"` (you render them).
positionGlobalFilter#"left" | "right" | "none"Which toolbar region the global search renders in. Default "right" (the internal-actions cluster). "left" places it next to the title/actions; "none" hides it (same as `enableGlobalFilter: false`).
positionToolbarAlertBanner#"top" | "bottom" | "head-overlay" | "none"Where the row-selection alert banner renders: above the table (`"top"`, default), below it (`"bottom"`), over the header row (`"head-overlay"`, with the select-all checkbox, so selecting rows does not move the table; needs the table head), or nowhere (`"none"`).
positionToolbarDropZone#"top" | "bottom" | "both" | "none"Where the group-by drop zone renders (grouping only). Default "top".
enableRowSelection#booleanWhether rows can be selected.
selectAllMode#"page" | "all"Select-all scope for the header checkbox: the current page ("page", default) or every row ("all").
enableSelectAll#booleanShow the select-all checkbox in the selection column header. Default true.
enableBatchRowSelection#booleanShift-click a row's checkbox to select or clear the range since the last click.
enableTopToolbar#booleanShows the toolbar above the table (title, search, filters, view options). Default `true`.
enableBottomToolbar#booleanShows the toolbar below the table (pagination, custom actions). Default `true`.
enableDensityToggle#booleanShow the density toggle in the toolbar. Default true.
enableFullscreenToggle#booleanShow the full-screen toggle in the toolbar. Default true.
enableToolbarInternalActions#booleanShow the toolbar's internal icon-action cluster (search, filters, column visibility, density, full screen). Default true. Hides the whole cluster at once; use the per-item flags for finer control.
enableKeyboardNavigation#booleanCell keyboard navigation with a single Tab stop: arrow keys, Home/End, PageUp/PageDown, Enter or F2 to activate a cell, Ctrl+C to copy it. Also makes the table an ARIA grid. Default `true`.
enableAnimations#booleanAnimate the table: rows glide when their order changes, fade in and out when they enter or leave the data, detail panels open and close smoothly, and the sort arrow, selection checkboxes and selected count transition. Always off when the user prefers reduced motion. Retime it with the CSS variables `--dt-motion-duration`, `--dt-motion-duration-fast` and `--dt-motion-ease` on the table.
title?#React.ReactNodeHeading shown at the start of the top toolbar.
renderTopToolbarCustomActions?#( props: DataTableSlotProps<TData> ) => React.ReactNodeCustom content rendered in the top toolbar's left region (next to the title), e.g. bulk-action buttons.
renderTopToolbar?#(props: DataTableSlotProps<TData>) => React.ReactNodeReplace the entire top toolbar with custom content.
renderBottomToolbar?#(props: DataTableSlotProps<TData>) => React.ReactNodeReplace the entire bottom toolbar (pagination region) with custom content.
renderToolbarInternalActions?#( props: DataTableSlotProps<TData> ) => React.ReactNodeReplace the top toolbar's internal icon-action cluster with custom content.
renderBottomToolbarCustomActions?#( props: DataTableSlotProps<TData> ) => React.ReactNodeCustom content rendered in the bottom toolbar's left region (next to pagination), e.g. summary text or actions.
renderCaption?#(props: DataTableSlotProps<TData>) => React.ReactNodeRender a `<caption>` for the table (e.g. an accessible summary).
renderEmpty?#(props: DataTableSlotProps<TData>) => React.ReactNodeContent shown when there are no rows. Defaults to `localization.noRecordsToDisplay`.

Everything else is TanStack

All standard instance methods — getState, getRowModel, getColumn, setPageIndex, getFilteredRowModel, resetSorting, … — are available directly on table as usual.