Shadcn React Table

Search documentation

Search the docs

Migrating from Material React Table

The data table follows Material React Table (MRT) closely: the same hook-then-component shape, most of the same options, and the same TanStack Table underneath. Moving a table over is mostly renaming. This page lists what changes.

The basics

tsx
// Material React Table
const table = useMaterialReactTable({ columns, data })
return <MaterialReactTable table={table} />

// This data table
const table = useDataTable({ columns, data, getRowId: (row) => row.id })
return <DataTable table={table} />
  • Type columns with DataTableColumnDef<TData> instead of MRT_ColumnDef<TData>.
  • Pass getRowId — row selection, editing and pinning key rows by id.
  • The table runs on TanStack Table v9, MRT on v8. The column options you share with TanStack (accessorKey, cell, header, footer, sortFn, filterFn, enableSorting, …) keep TanStack's names; v9 renames a few v8 ones, such as sortingFn → sortFn.

Column options

MRT puts its own column options on the column definition. Here they live under meta.

MRT column optionHere
Cell / Header / Footercell / header / footer (TanStack's)
filterVariantmeta.filterVariant
filterSelectOptionsmeta.filterSelectOptions
filterFn (a mode name)meta.filterMode
columnFilterModeOptionsmeta.columnFilterModeOptions
enableColumnFilterModesmeta.enableColumnFilterModes
Filtermeta.renderColumnFilter
editVariant / editSelectOptionsmeta.editVariant / meta.editSelectOptions
enableEditingmeta.enableEditing
Editmeta.renderEditCell
muiEditTextFieldProps validationmeta.validate (return a message to block the save)
GroupedCell / AggregatedCell / PlaceholderCellmeta.renderGroupedCell / meta.renderAggregatedCell / meta.renderPlaceholderCell
enableClickToCopymeta.enableClickToCopy
enableColumnActionsmeta.enableColumnActions
visibleInShowHideMenumeta.visibleInShowHideMenu
growmeta.grow (in layoutMode: "grid", a weight: every data column grows by 1 unless set; see Column resizing)
muiTableHeadCellProps / muiTableBodyCellProps / muiTableFooterCellPropsmeta.slotProps.headCell / .bodyCell / .footerCell

Component props (mui*Props)

MRT's mui*Props become one slotProps option. Each part takes props or a function of its context, and merges them with the table's own. See Part props.

MRTslotProps part
muiTablePaperPropsroot
muiTableContainerPropssurface
muiTablePropstable
muiTableHeadProps / muiTableHeadRowProps / muiTableHeadCellPropshead / headRow / headCell
muiFilterTextFieldProps (cell)filterCell
muiTableBodyProps / muiTableBodyRowProps / muiTableBodyCellPropsbody / bodyRow / bodyCell
muiDetailPanelPropsdetailPanel
muiTableFooterProps / muiTableFooterRowProps / muiTableFooterCellPropsfooter / footerRow / footerCell
muiTopToolbarProps / muiBottomToolbarPropstopToolbar / bottomToolbar
muiPaginationPropspagination
muiToolbarAlertBannerPropsalertBanner
muiSearchTextFieldPropssearchInput
muiEditTextFieldPropseditField
muiEditRowDialogProps / muiCreateRowModalPropseditDialog (isCreating tells them apart)
muiSelectCheckboxPropsselectCheckbox

State

MRT stateHere
isFullScreenisFullscreen
columnFilterFnscolumnFilterModes
globalFilterFnglobalFilterMode
editingRoweditingRowId (the draft is in rowDraft)
editingCelleditingCell ({ rowId, columnId })
creatingRowisCreating (the draft is in rowDraft)
isLoading / isSaving / showProgressBars / showSkeletons / showLoadingOverlayoptions of the same names, not state
density, showColumnFilters, and TanStack's own stateunchanged

Set and control state the same way: initialState, state, and the matching on…Change callback (onIsFullScreenChange → onIsFullscreenChange, onColumnFilterFnsChange → onColumnFilterModesChange, onGlobalFilterFnChange → onGlobalFilterModeChange). See State management.

Table options

Most options keep their MRT names: enableRowSelection, enableMultiRowSelection, enableBatchRowSelection, enableSelectAll, selectAllMode, enableEditing, editDisplayMode, createDisplayMode, positionCreatingRow, enableGrouping, enableColumnPinning, enableRowPinning, enableColumnOrdering, enableColumnResizing, enableRowOrdering, enableRowNumbers, enableRowVirtualization, enableColumnVirtualization, rowVirtualizerOptions, columnVirtualizerOptions, enableStickyHeader, enableStickyFooter, enableTableHead, enableTableFooter, enableExpandAll, enableColumnFilterModes, enableGlobalFilterModes, enableGlobalFilterRankedResults, enableFacetedValues, enableFilterMatchHighlighting, enableClickToCopy, enableCellActions, enableDensityToggle, enableFullScreenToggle → enableFullscreenToggle, enableTopToolbar, enableBottomToolbar, enableToolbarInternalActions, columnFilterDisplayMode, paginationDisplayMode, positionPagination, positionGlobalFilter, positionActionsColumn, positionExpandColumn, positionToolbarAlertBanner, positionToolbarDropZone, displayColumnDefOptions, defaultDisplayColumn, filterFns, aggregationFns, columnFilterModeOptions, globalFilterModeOptions, localization, icons.

Renamed or reshaped:

MRTHere
sortingFnssortFns (TanStack v9's name)
rowNumberDisplayModerowNumberMode
renderEmptyRowsFallbackrenderEmpty
muiPaginationProps.rowsPerPageOptionspageSizeOptions
state.isLoading and friendsthe isLoading, isSaving, showProgressBars, showSkeletons, showLoadingOverlay options
onEditingRowSave({ values, table }), then table.setEditingRow(null)onEditingRowSave({ row, values, table, exit }), then exit()
onCreatingRowSave({ values, table }), then table.setCreatingRow(null)onCreatingRowSave({ values, table, exit }), then exit()
cell edits saved from muiEditTextFieldProps.onBluronEditingCellSave({ row, column, value, table })
displayColumnDefOptions["mrt-row-select"] (and the other mrt-row-* ids)displayColumnDefOptions["cn-select"] — ids: cn-select, cn-expand, cn-row-actions, cn-row-number, cn-row-pin, cn-row-drag

Callbacks and render options with the same name and arguments: onEditingRowCancel, onCreatingRowCancel, renderTopToolbarCustomActions, renderBottomToolbarCustomActions, renderToolbarInternalActions, renderTopToolbar, renderBottomToolbar, renderRowActions, renderDetailPanel, renderCaption, renderEditRowDialogContent, renderCreateRowDialogContent, renderColumnFilterModeMenuItems, renderGlobalFilterModeMenuItems, and the menu callbacks renderColumnActionsMenuItems, renderRowActionMenuItems, renderCellActionMenuItems (each receives internalMenuItems and closeMenu).

The table instance

MRTHere
table.setEditingRow(row)table.beginRowEdit(row)
table.setEditingRow(null) / table.setCreatingRow(null)table.cancelEdit()
table.setCreatingRow(true)table.beginCreate()
table.setEditingCell(cell)table.setEditingCell({ rowId, columnId })
table.setIsFullScreen(…)table.setIsFullscreen(…)
table.setColumnFilterFns(…)table.setColumnFilterMode(columnId, mode)
table.setGlobalFilterFn(…)table.setGlobalFilterMode(mode)
table.refs.tableContainerRef (and the other refs)table.dataTable.refs.tableContainerRef
table.options.enableEditing (and MRT's other options)table.dataTable.enableEditing
table.getState()unchanged, including the UI state above

The instance is stable and the component that calls useDataTable does not re-render on state changes. Read state where you render it with table.Subscribe, or pass stateSelector. See State management.

Defaults that differ

OptionMRTHereWhy
editDisplayMode"modal""cell"Inline editing is the quickest edit for most tables
positionActionsColumn"first""last"Actions read best after the data they act on
enableStickyHeaderfalsetrueHeaders stay useful on long tables
enableFacetedValuesfalsetrueSelect filters fill their options from the data
enableGlobalFilterRankedResultstruefalseSearching never reorders rows unless you opt in
Text filter mode"fuzzy""contains"Predictable matches; fuzzy is one menu click away
Cell editing starts ondouble-clicksingle clickOne click to edit, matching the click-to-edit affordance

Set the MRT value explicitly to keep the old behavior.

Not here (yet)

  • rowPinningDisplayMode values "sticky" and "select-sticky" (rows that stick in place); use "top-and-bottom" or "select-top".
  • enableColumnDragging as a separate switch.
  • MRT's enableRowDragging works through DataTableDndProvider and onRowDragEnd here; see Row dragging.
  • MUI theming: the table uses your shadcn/ui components and theme instead.