Shadcn React Table

Search documentation

Search the docs

Row selection

Set enableRowSelection: true to add a leading checkbox column. When rows are selected, a selection alert banner appears showing the current count.

enableRowSelection accepts a boolean or a (row) => boolean predicate (standard TanStack), so you can allow selecting only certain rows.

Stable selection keys

Always provide getRowId so selection keys stay stable across re-renders, sorting, and pagination. Without it, selection is keyed by row index and can drift.

row-selection

Multi-row selection with a select-all checkbox in the header.

Row selection
GitHub
ID
AvaThompsonOwnerEngineeringactive22$45,000Jan 2, 2023
0%
LiamNguyenAdminMarketinginactive25$47,137Jan 13, 2023
9%
NoahSilvaEditorDesignpending28$49,274Jan 24, 2023
18%
EmmaCarterViewerSalesactive31$51,411Feb 4, 2023
27%
OliviaRossiOwnerSupportinactive34$53,548Feb 15, 2023
36%
WilliamWalkerAdminEngineeringpending37$55,685Feb 26, 2023
45%
SophiaPatelEditorMarketingactive40$57,822Mar 9, 2023
54%
JamesMullerViewerDesigninactive43$59,959Mar 20, 2023
63%
IsabellaParkOwnerSalespending46$62,096Mar 31, 2023
72%
LucasReyesAdminSupportactive49$64,233Apr 11, 2023
81%
$4,120,536
Rows per page
1–10 of 48
const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableRowSelection: true,
})

return <DataTable table={table} />

Read the current selection at any time:

const selected = table.getState().rowSelection

Or control it from your own state:

const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableRowSelection: true,
  state: { rowSelection },
  onRowSelectionChange: setRowSelection,
})

You can also gate selection per row with a predicate:

enableRowSelection: (row) => row.original.status !== "archived"

single-selection

For radio-like single selection (no select-all checkbox), add enableMultiRowSelection: false.

Single selection
GitHub
ID
AvaThompsonOwnerEngineeringactive22$45,000Jan 2, 2023
0%
LiamNguyenAdminMarketinginactive25$47,137Jan 13, 2023
9%
NoahSilvaEditorDesignpending28$49,274Jan 24, 2023
18%
EmmaCarterViewerSalesactive31$51,411Feb 4, 2023
27%
OliviaRossiOwnerSupportinactive34$53,548Feb 15, 2023
36%
WilliamWalkerAdminEngineeringpending37$55,685Feb 26, 2023
45%
SophiaPatelEditorMarketingactive40$57,822Mar 9, 2023
54%
JamesMullerViewerDesigninactive43$59,959Mar 20, 2023
63%
IsabellaParkOwnerSalespending46$62,096Mar 31, 2023
72%
LucasReyesAdminSupportactive49$64,233Apr 11, 2023
81%
$4,120,536
Rows per page
1–10 of 48
const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableRowSelection: true,
  enableMultiRowSelection: false,
})

return <DataTable table={table} />

Select-all behavior

The selection column header carries a select-all checkbox. selectAllMode controls its scope — "page" (default) toggles the current page, "all" toggles every row across pages. Set enableSelectAll: false to hide the header checkbox entirely.

const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableRowSelection: true,
  selectAllMode: "all", // "page" | "all"
  enableSelectAll: true,
})

Relevant options

PropTypeDefaultDescription
enableSelectAll?booleantrueShow the select-all checkbox in the selection column header. Default true.
selectAllMode?"page" | "all""page"Select-all scope for the header checkbox: the current page ("page", default) or every row ("all").