Shadcn React Table

Search documentation

Search the docs

Quick start

A minimal table is two pieces: columns (TanStack column defs, typed with DataTableColumnDef) and a call to useDataTable, whose result you hand to <DataTable />.

  1. Define columns

    Columns are TanStack column defs, typed with DataTableColumnDef. Give rows a stable id so selection and state survive re-renders.

    tsx
    "use client"
    
    import * as React from "react"
    import {
      DataTable,
      useDataTable,
      type DataTableColumnDef,
    } from "@/components/ui/data-table"
    
    type Person = { id: string; name: string; email: string; age: number }
    
    const data: Person[] = [
      { id: "1", name: "Ada Lovelace", email: "ada@example.com", age: 36 },
      { id: "2", name: "Alan Turing", email: "alan@example.com", age: 41 },
      { id: "3", name: "Grace Hopper", email: "grace@example.com", age: 85 },
    ]
    
    const columns: DataTableColumnDef<Person>[] = [
      { accessorKey: "name", header: "Name" },
      { accessorKey: "email", header: "Email" },
      { accessorKey: "age", header: "Age", meta: { align: "right" } },
    ]
    
  2. Create the table

    Inside your component, pass data and columns to useDataTable. Everything else is optional; getRowId gives rows a stable identity and initialState seeds the page size.

  3. Render it

    Hand the instance to <DataTable />.

    tsx
    export function PeopleTable() {
      const table = useDataTable({
        data,
        columns,
        getRowId: (row) => row.id,
        initialState: { pagination: { pageSize: 10 } },
      })
    
      return <DataTable table={table} />
    }
    

That already gives you sorting, client pagination, a toolbar with global search, column visibility, and density controls:

BasicSorting + client pagination — the default feature set.
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

Turning features on

Every feature is an option on useDataTable. Flip a flag to enable it — for example, multi-column sorting, per-column filters, and row selection:

tsx
const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableMultiSort: true,
  initialState: { showColumnFilters: true },
  enableRowSelection: true,
})

Memoize data and columns

Pass stable references for data and columns (e.g. via React.useMemo or module scope). Handing TanStack a new columns identity every render can reset state.

MinimalA plain, read-only table with the built-ins turned off.
GitHub
ID
First name
Last name
Email
Role
Department
Status
Age
Salary
Start date
Progress
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%
$419,836

Where to go next

  • Usage — the options-in / instance-out model and table.dataTable.
  • Guides — enable each feature, with live examples.
  • API reference — every option and its default.