Selection

Built-in row selection, controlled id-based selection, and bulk actions with SelectionToolbar.

DataTable supports two selection modes:

ModeBest ForRequirements
Built-in selectionLocal table state with a simple selected fieldRows include selected; pass onDataChange
Controlled id selectionRemote data, virtualization, persisted selectionPass getRowId, selection, and onSelectionChange

Built-in Selection

Built-in selection is the shortest path when the table owns the row array and each row can carry a selected field.

const [employees, setEmployees] = useState(
  sampleEmployees.map((employee) => ({ ...employee, selected: false })),
);

<DataTable
  data={employees}
  columns={selectionColumns}
  enableRowSelection
  onDataChange={setEmployees}
/>

Controlled Id-based Selection

Use controlled selection when row data comes from a server, a cache, or another store that should not be mutated by the table.

const [employees] = useState(sampleEmployees);
const [selection, setSelection] = useState<RowSelectionState>({});

<DataTable
  data={employees}
  columns={selectionColumns}
  enableRowSelection
  getRowId={(employee) => employee.id}
  selection={selection}
  onSelectionChange={setSelection}
/>

Stable row ids matter here. Without getRowId, TanStack falls back to row indexes, which are fragile once sorting, filtering, or virtualization enter the picture.

Bulk Actions

SelectionToolbar is a primitive, but it composes naturally with DataTable selection state for bulk actions.

For controlled id-based selection, derive selectedCount from the selection map instead of the row objects.

API Reference

PropTypeDefaultDescription
enableRowSelectionbooleanfalseAdd the selection checkbox column
selectionRowSelectionState-Controlled id-based selection state
onSelectionChange(selection: RowSelectionState) => void-Controlled selection change handler
onDataChange(data: TData[]) => void-Required for built-in selection mode
getRowId(row: TData, index: number) => string-Stable ids for controlled selection
clearSelectionOnOutsideClickbooleanfalseClear the current selection on outside click

On this page