Tutorial · September 26, 2026 · 5 min read
How to add a data table with sorting, search and pagination in React
To add a data table with sorting, search and pagination in React, install ReactFrame's free Data Table with npx shadcn@latest add @reactframe/data-table, describe your columns once and pass your rows as plain objects. Sorting, search, column filters, status tabs, pagination and row selection then work in the browser, which suits lists of up to a few thousand rows.
Admin panels, dashboards and internal tools all end up needing the same table: sortable columns, a search box, status tabs, pagination and a few row actions. Libraries like TanStack Table give you the logic but leave the UI to you. This tutorial uses ReactFrame's free Data Table, which ships both.
1. Install
npx shadcn@latest add @reactframe/data-table
2. Describe your columns and pass your rows
import { DataTable, type DataTableColumn } from "@/components/data-table";
const columns: DataTableColumn[] = [
{ key: "name", label: "Customer", type: "avatar", sortable: true },
{ key: "email", label: "Email", type: "text", sortable: true, filterable: true },
{ key: "plan", label: "Plan", type: "badge", sortable: true, filterable: true },
{ key: "mrr", label: "MRR", type: "currency", sortable: true, align: "right" },
{ key: "status", label: "Status", type: "badge", filterable: true },
{ key: "actions", label: "", type: "actions", align: "right" },
];
const rows = [
{ name: "Ada Lovelace", email: "ada@acme.com", plan: "Pro", mrr: 49, status: "Active" },
{ name: "Alan Turing", email: "alan@acme.com", plan: "Team", mrr: 199, status: "Active" },
{ name: "Grace Hopper", email: "grace@acme.com", plan: "Free", mrr: 0, status: "Inactive" },
];
export function CustomersTable() {
return <DataTable title="Customers" columns={columns} data={rows} rowsPerPage={10} />;
}
Each row is a plain object; the column key says which field it reads. The column type decides how the cell looks:
| Type | Renders |
|---|---|
text | Plain text. |
number | A number, right for IDs and counts. |
currency | A dollar amount with two decimals. |
badge | A pill, coloured by badgeColors. |
avatar | Initials in a coloured circle next to the name. |
actions | Icon buttons from actionButtons. |
3. Search, filters and tabs
- Search (
showSearch) matches every column. - Column filters: columns with
filterable: trueget a filter menu in the header, listing that column's values. - Status tabs (
showStatusTabs) build tabs from the values of one column,statusby default; pointstatusTabsColumnat another field if needed. - Pagination (
showPagination,rowsPerPage) and row selection (selectable) are on by default.
4. Colour the badges
<DataTable
columns={columns}
data={rows}
badgeColors={[
{ value: "Active", background: "rgba(135,255,227,0.12)", text: "#87FFE3", dot: true },
{ value: "Inactive", background: "rgba(255,255,255,0.08)", text: "rgba(255,255,255,0.6)", dot: true },
{ value: "Pro", background: "rgba(124,92,255,0.14)", text: "#B6A6FF" },
]}
/>
When to reach for something else
This table sorts, searches and pages in the browser, which is ideal up to a few thousand rows. For tens of thousands of rows or data that lives on the server, page and filter in your API and pass one page of results at a time, or use a headless library such as TanStack Table for the logic.
Related
Pair the table with charts and stat cards in the Dashboard kit.

Ahmet Loca · Product designer
Hi, I'm Ahmet. I have over four years of experience creating intuitive, user-focused designs for digital products, and ReactFrame is where that work becomes components you can use in your own.