Export Selected Rows
Tick the rows you need, across as many pages as you like, and export only those to CSV or Excel. The selection count and the export button stay in sync, and nothing downloads until something is selected.
$ npx shadcn add https://www.shad-table.dev/r/export-selected-table.json| Name | Company | Plan | MRR | ||
|---|---|---|---|---|---|
| Ava Thompson | ava@northwind.com | Northwind | Enterprise | $4,200 | |
| Liam Chen | liam@globex.com | Globex | Pro | $290 | |
| Sofia Patel | sofia@initech.com | Initech | Pro | $290 | |
| Noah Garcia | noah@umbrella.com | Umbrella | Free | $0 | |
| Mia Johnson | mia@hooli.com | Hooli | Enterprise | $3,800 | |
| Ethan Kim | ethan@vandelay.com | Vandelay | Pro | $580 | |
| Isabella Rossi | isabella@starkindustries.com | Stark Industries | Enterprise | $6,100 | |
| Lucas Martin | lucas@wayneenterprises.com | Wayne Enterprises | Pro | $290 |
1–8 of 25
How it works
1.Selection is keyed by id, so it survives pagination
By default TanStack keys selection by row index, so row 3 on page 1 and row 3 on page 2 would share a checkbox. getRowId makes the key the customer's id, so ticking rows on several pages builds one selection.
const table = useReactTable({data,columns,getRowId: (row) => row.id,state: { rowSelection },onRowSelectionChange: setRowSelection,// ...})
2.The header checkbox covers the page, "Select all" covers the table
The header box uses toggleAllPageRowsSelected, so it only touches the rows the user can see, and shows a dash when some of them are selected. Once the whole page is ticked, a "Select all 25" link offers the rest, the same pattern Gmail uses.
checked={table.getIsAllPageRowsSelected()? true: table.getIsSomePageRowsSelected() ? 'indeterminate' : false}onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
3.Export reads the selected row model, not the visible rows
getSelectedRowModel() returns every selected row across all pages, in table order. The select column is skipped, and values come from row.getValue() so the file gets 4200 rather than "$4,200".
const selectedRows = table.getSelectedRowModel().rowsconst rows = selectedRows.map((row) =>exportColumns.map((column) => String(row.getValue(column.id) ?? '')),)