Table Builder
Generate production-ready data tables with sorting, filtering, and pagination.
Core Workflow Define columns: Column configuration with types Choose mode: Server-side or client-side rendering Add features: Sorting, filtering, pagination, search Row actions: Edit, delete, view actions Empty states: No data and error views Loading states: Skeletons and suspense Mobile responsive: Stack columns or horizontal scroll Column Configuration import { ColumnDef } from "@tanstack/react-table";
export const columns: ColumnDef
React Table Implementation "use client";
import { useReactTable, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel, flexRender, } from "@tanstack/react-table";
export function DataTable
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, onPaginationChange: setPagination, state: { sorting, columnFilters, pagination }, });
return (
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<DataTablePagination table={table} />
</div>
); }
Server-Side Pattern // app/users/page.tsx import { DataTable } from "@/components/ui/data-table";
async function getUsers(params: {
page: number;
pageSize: number;
sortBy?: string;
sortOrder?: "asc" | "desc";
search?: string;
}) {
const response = await fetch(/api/users?${new URLSearchParams(params)});
return response.json();
}
export default async function UsersPage({ searchParams, }: { searchParams: { page?: string; search?: string }; }) { const page = Number(searchParams.page) || 1; const search = searchParams.search || "";
const { data, totalPages } = await getUsers({ page, pageSize: 10, search });
return (
Users
Pagination Component
export function DataTablePagination({ table }: { table: Table Rows per page
Row Actions
function RowActions({ row }: { row: Row
return (
/users/${user.id})}>
View Details
Empty State export function EmptyState() { return (
No data found
Get started by creating a new record.
Loading Skeleton export function TableSkeleton() { return (
Best Practices Use TanStack Table for complex features Server-side pagination for large datasets Debounce search inputs Persist sorting/filtering in URL params Mobile: Horizontal scroll or card view Accessibility: Keyboard navigation, ARIA Output Checklist Column definitions with types Sorting functionality Filtering/search Pagination controls Row actions menu Empty state component Loading skeleton Mobile responsive URL state persistence Accessibility attributes
← 返回排行榜