Implementation with Claude Code
Learn about implementation using Claude Code. Practical tips and code examples included.
テーブルコンポーネントの要件
データテーブルは管理画面やダッシュボードの中心的なUIです。ソート、フィルター、ページネーション、列のリサイズなど多くの機能が求められます。Claude Codeを使えば、TanStack Tableをベースに高機能なテーブルを素早く構築できます。
TanStack Tableによる基本実装
> TanStack Tableを使ったソート・フィルター付きテーブルを作って。
> 型安全で、カラム定義を宣言的に書けるようにして。
import {
useReactTable, getCoreRowModel, getSortedRowModel,
getFilteredRowModel, getPaginationRowModel,
flexRender, createColumnHelper, SortingState,
} from '@tanstack/react-table';
import { useState } from 'react';
interface User {
id: string;
name: string;
email: string;
role: string;
createdAt: string;
}
const columnHelper = createColumnHelper<User>();
const columns = [
columnHelper.accessor('name', {
header: '名前',
cell: (info) => <span className="font-medium">{info.getValue()}</span>,
}),
columnHelper.accessor('email', {
header: 'メールアドレス',
}),
columnHelper.accessor('role', {
header: '権限',
cell: (info) => (
<span className={`px-2 py-1 rounded text-xs ${
info.getValue() === 'admin' ? 'bg-red-100 text-red-700' : 'bg-gray-100'
}`}>
{info.getValue()}
</span>
),
}),
columnHelper.accessor('createdAt', {
header: '登録日',
cell: (info) => new Date(info.getValue()).toLocaleDateString('en-US'),
}),
];
function DataTable({ data }: { data: User[] }) {
const [sorting, setSorting] = useState<SortingState>([]);
const [globalFilter, setGlobalFilter] = useState('');
const table = useReactTable({
data,
columns,
state: { sorting, globalFilter },
onSortingChange: setSorting,
onGlobalFilterChange: setGlobalFilter,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});
return (
<div>
<input
value={globalFilter}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="検索..."
className="mb-4 px-3 py-2 border rounded w-full max-w-sm"
/>
<table className="w-full border-collapse" role="grid">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th
key={header.id}
onClick={header.column.getToggleSortingHandler()}
className="px-4 py-3 text-left bg-gray-50 border-b cursor-pointer select-none"
aria-sort={header.column.getIsSorted() === 'asc' ? 'ascending' : header.column.getIsSorted() === 'desc' ? 'descending' : 'none'}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{ asc: ' ↑', desc: ' ↓' }[header.column.getIsSorted() as string] ?? ''}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id} className="hover:bg-gray-50">
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className="px-4 py-3 border-b">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
<Pagination table={table} />
</div>
);
}
ページネーション
function Pagination({ table }: { table: any }) {
return (
<div className="flex items-center justify-between mt-4">
<span className="text-sm text-gray-500">
全{table.getFilteredRowModel().rows.length}件中{' '}
{table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}〜
{Math.min(
(table.getState().pagination.pageIndex + 1) * table.getState().pagination.pageSize,
table.getFilteredRowModel().rows.length
)}件
</span>
<div className="flex gap-2">
<button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}
className="px-3 py-1 border rounded disabled:opacity-50">Previous</button>
<button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}
className="px-3 py-1 border rounded disabled:opacity-50">Next</button>
</div>
</div>
);
}
行選択と一括操作
const [rowSelection, setRowSelection] = useState({});
// テーブル設定に追加
const table = useReactTable({
// ...既存の設定
state: { sorting, globalFilter, rowSelection },
onRowSelectionChange: setRowSelection,
enableRowSelection: true,
});
// 一括操作ボタン
const selectedCount = Object.keys(rowSelection).length;
{selectedCount > 0 && (
<div className="mb-4 p-3 bg-blue-50 rounded flex items-center gap-4">
<span>{selectedCount}件選択中</span>
<button onClick={() => handleBulkDelete(table.getSelectedRowModel().rows)}>
一括Delete
</button>
</div>
)}
Summary
Claude Codeを使えば、TanStack Tableベースの高機能テーブルをソート・フィルター・ページネーション付きで素早く構築できます。データの可視化はデータ可視化の記事を、カレンダー表示はカレンダーコンポーネントを参照してください。
TanStack Tableの詳細はTanStack Table公式ドキュメントをご覧ください。
Free PDF: Claude Code Cheatsheet in 5 Minutes
Just enter your email and we'll send you the single-page A4 cheatsheet right away.
We handle your data with care and never send spam.
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
7 CLAUDE.md Templates for Claude Code You Can Copy Into Real Projects
Copy-paste 7 practical CLAUDE.md templates for solo apps, content sites, APIs, teams, and legacy codebases, plus the failure cases to avoid.
Claude Code Approval and Sandbox Guide | Safe Daily Settings for Real Work
Learn how to split Claude Code actions into allow, ask, deny, and sandboxed workflows with working settings, hooks, and rollout examples.
Complete Beginner's Guide to Claude Code 2026 | 7 Steps from Zero to Production-Ready
A complete beginner's guide for first-time Claude Code users. From installation to integrating it into your real development workflow — covering every pitfall Masa ran into when starting out.
Related Products
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.