Skip to main content

<DataTable> props

Every prop, grouped by area. Use the search (top right) to find a setting fast.

Data

PropTypeDefaultDescription
columnsColumnDef<T>[]TanStack column definitions (+ align, type, wrapText, export options).
dataT[][]Row data (client mode).
rowCountnumberTotal row count (server mode).
getRowId(row, index) => stringStable row id; defaults to row[idKey].
idKeykeyof T'id'Shorthand row-id field.
dataMode'client' | 'server''client'Client-held or server-fetched.
onFetchData(filters, meta) => Promise<{ data, total }>Server fetch handler.
initialStatePartial<TableState>Initial sorting/pagination/pinning/visibility/sizing/density.
stateKeystringPersist view state under this key (see State persistence).
persistPersistOptionsTune persistence: storage ('local'/'session'/custom), include, debounceMs.
onDataStateChange(state) => voidAny table-state change.

Sorting / Filtering / Pagination

PropTypeDefaultDescription
enableSortingbooleantrueColumn sorting.
sortingMode'client' | 'server''client'Sort locally or on the server.
enableGlobalFilterbooleantrueToolbar search.
enableColumnFilterbooleanfalseColumn-filter rule builder.
filterMode'client' | 'server''client'Filter locally or on the server.
enablePaginationbooleanfalsePagination footer.
paginationMode'client' | 'server''client'Paginate locally or on the server.

Selection

PropTypeDefaultDescription
enableRowSelectionboolean | (row) => booleanfalseSelection checkbox column.
enableMultiRowSelectionbooleantrueAllow multiple selection.
selectMode'page' | 'all''page'Select-all scope.
isRowSelectable({ row, id }) => booleanDisable specific rows.
enableBulkActionsbooleanfalseBulk-actions bar.
renderBulkActions(selection) => ReactNodeCustom bulk actions.
onSelectionChange(selection) => voidSelection changed.

Columns

PropTypeDefaultDescription
enableColumnResizingbooleanfalseDrag to resize.
columnResizeMode'onChange' | 'onEnd''onChange'Live vs on-release.
enableColumnReorderingbooleanfalseDrag headers to reorder.
enableColumnPinningbooleanfalseSticky left/right.
enableColumnVisibilitybooleantrueShow/hide from toolbar.

Appearance & layout

PropTypeDefaultDescription
density'compact' | 'standard' | 'comfortable'Controlled density — overrides the selector.
defaultDensity'compact' | 'standard' | 'comfortable''standard'Uncontrolled initial density; the selector can still change it.
stripedbooleanfalseAlternate row background.
hoverbooleantrueHighlight the hovered row.
fitToScreenbooleantrueStretch columns to fill width.
stickyHeaderbooleanPin the header; on its own it bounds the body at maxHeight (see Height & scrolling).
stickyFooterbooleanPin the pagination footer; like stickyHeader, it bounds the body.
maxHeightstring | number480¹Cap the scroll viewport; active on its own. ¹Default applied only in a bounded mode.
heightstring | numberFix the grid height ('100%' fills a sized parent); the body scrolls to fill.
minHeightstring | numberOptional floor so a near-empty grid doesn't collapse.
enableVirtualizationbooleanfalseRender only visible rows.
estimatedRowHeightnumber52Virtualizer row-height estimate.
getRowClassName({ row, index }) => stringConditional row class.
getCellClassName({ row, columnId, value }) => stringConditional cell class.

Toolbar

PropTypeDefaultDescription
enableDensitySelectorbooleanfalseDensity menu.
enableExportbooleanfalseExport menu.
enableResetbooleanfalseReset button.
enableRefreshbooleanfalseRefresh button.
extraFilterReactNodeCustom toolbar content (right side by default).
renderToolbar(controls) => ReactNodeRearrange the built-in toolbar controls (guide).

States & customization

PropTypeDefaultDescription
loadingbooleanfalseShow skeleton rows.
noRowsMessagestring | ReactNode'No rows'Empty-state message.
skeletonRowsnumber5Skeleton row count.
slotsPartial<DataTableSlots>Replace any sub-component.
slotPropsPartialSlotPropsInject props/sx into parts.
apiRefRefObject<DataTableApi<T>>Imperative handle.
sxSxPropsRoot styles.
onRowClick(event, row) => voidRow click.
selectOnRowClickbooleanfalseToggle selection on row click.
loggingboolean | DataTableLoggingOptionsfalseDebug logging.

Slots & slotProps

slots replaces a part; slotProps injects props/sx into one — the MUI pattern. Slots are a flat map of descriptive keys (not nested by section); pass only what you want to override, and each falls back to the built-in.

Structure slots

SlotPart
root, scroller, gridouter card / scroll area / grid
header, headerRow, headerCellheader parts
body, row, cell, detailPanelbody parts
footer, paginationfooter / pagination
loadingOverlay, noRowsOverlayoverlays

Toolbar & control slots

SlotPart
toolbarthe whole toolbar
searchInputglobal search field
columnFilterControl, columnVisibilityControl, columnPinningControl, densityControltoolbar menus
exportButton, refreshButton, resetButtontoolbar buttons
bulkActionsToolbarselection bulk-actions bar

Icon slots

Swap in your own set (e.g. lucide); defaults are built-in line icons. See Custom icons.

SlotUsed for
searchIcon, clearIconsearch / clear
filterIcon, addFilterIconcolumn filter
columnsIconcolumns panel (show/hide, pin, reorder)
densityIcon, exportIcon, refreshIcon, resetIcontoolbar buttons
sortIconAsc, sortIconDescheader sort
expandIcon, collapseIconrow expand / collapse

slotProps accepts the same keys, plus selectionColumn / expandColumn to configure the auto-generated checkbox / expander columns — e.g. slotProps={{ selectionColumn: { enablePinning: true } }}.

Height & scrolling

The grid is a flex column — header pinned to the top, footer to the bottom, body scrolling between. Three height modes: auto (default, grows to content), maxHeight (caps and scrolls), and height (fixed, or "100%" to fill a sized parent). A bounded height is all the body needs to scroll — minHeight is not required.

See Height & scrolling for the full guide with a live demo of each mode.

State persistence

Give the grid a stable stateKey and it remembers its view state — pagination, sort, global search, column filters, column order / width / visibility / pinning, and density — across reloads and remounts, with no save/restore wiring:

<DataTable columns={columns} data={rows} stateKey="expenses" enablePagination enableColumnPinning />

Try it — sort, paginate, reorder/resize/hide a column, then reload the page: the view comes back.

Loading demo…

It reads the saved snapshot into initialState on mount and writes (debounced) on change. Selection and row expansion are excluded by default. Tune it with persist:

<DataTable
stateKey="expenses"
persist={{
storage: 'session', // 'local' (default) | 'session' | a custom Storage-like object
include: ['sorting', 'pagination', 'columnPinning'], // whitelist (default: all but selection/expansion)
debounceMs: 500, // write throttle (default 300)
}}
/>

SSR-safe (no-ops without window; a custom storage object is honored anywhere). Storage keys are namespaced as dt:<stateKey>. To forget a saved view (e.g. a "Reset" button), call clearPersistedState(stateKey, persist?) and remount/reload.

Dark mode & cssVariables themes

The grid derives every colour from your MUI theme, so it follows light/dark automatically — including the modern setup createTheme({ cssVariables: true, colorSchemes: { light, dark } }): it reads palette values via theme.vars and emits its mode-dependent defaults with applyStyles('dark'). To customise grid colours per scheme, use createDataTableTheme (palette + optional darkPalette), which emits colorSchemes overrides that compose cleanly with a cssVariables app theme.