データグリッドライブラリ比較
3つのアプローチで編集可能なデータグリッドを実装し、機能とスタイルを比較
共通のサンプルデータ
社員情報テーブルを共通データとして使用しています。各デモではセルをダブルクリック(AG Gridはシングルクリック)して編集できます。
[
{
"name": "田中太郎",
"department": "エンジニアリング",
"position": "シニアエンジニア",
"salary": 7500000
},
{
"name": "佐藤花子",
"department": "デザイン",
"position": "UIデザイナー",
"salary": 6000000
},
{
"name": "鈴木一郎",
"department": "エンジニアリング",
"position": "テックリード",
"salary": 9000000
}
]... 他 5 件
1. AG Grid Community
業界標準のエンタープライズグリッド — ソート、フィルタ、セル編集などが内蔵
特徴
- • セルクリックで即座にインライン編集が可能
- • ソート・フィルタ・カラムリサイズが標準搭載
- • 大量データ(数万行)でも高速な仮想スクロール
- • Community版は無料、Enterprise版は有料機能あり
インストール
npm install ag-grid-react ag-grid-communitytsx
'use client';
import { AgGridReact } from 'ag-grid-react';
import { AllCommunityModule, ModuleRegistry, type ColDef } from 'ag-grid-community';
import { useState, useMemo } from 'react';
ModuleRegistry.registerModules([AllCommunityModule]);
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
const rowData: Employee[] = [
{ id: 1, name: '田中太郎', department: 'エンジニアリング', salary: 7500000 },
{ id: 2, name: '佐藤花子', department: 'デザイン', salary: 6000000 },
{ id: 3, name: '鈴木一郎', department: 'マーケティング', salary: 5500000 },
];
export function AgGridDemo() {
const columnDefs = useMemo<ColDef<Employee>[]>(() => [
{ field: 'id', headerName: 'ID', width: 80 },
{ field: 'name', headerName: '氏名', editable: true },
{ field: 'department', headerName: '部署', editable: true },
{
field: 'salary',
headerName: '年収',
editable: true,
valueFormatter: p => `¥${p.value.toLocaleString()}`,
},
], []);
const defaultColDef = useMemo(() => ({
sortable: true,
filter: true,
resizable: true,
}), []);
return (
<div className="ag-theme-alpine" style={{ height: 300, width: '100%' }}>
<AgGridReact rowData={rowData} columnDefs={columnDefs} defaultColDef={defaultColDef} />
</div>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、AG Grid Communityを使った編集可能なデータグリッドを実装してください。 - 使用ライブラリ: ag-grid-react、ag-grid-community(AllCommunityModule、ModuleRegistry) - AgGridReact コンポーネントと ColDef 型を使ってカラム定義を行うこと - editable: true でセルをクリックしてインライン編集できること - defaultColDef に sortable: true、filter: true、resizable: true を設定すること - valueFormatter でサラリー列を¥形式で書式化すること - onCellValueChanged コールバックで編集後のデータを state に反映すること - ag-theme-alpine クラスでスタイルを適用すること
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
2. TanStack Table(React Table v8)
ヘッドレスUIライブラリ — ロジックのみ提供し、表示は完全にカスタム可能
| ID | 氏名 | 部署 | 役職 | メール | 年収 | 入社日 |
|---|---|---|---|---|---|---|
| 1 | 田中太郎 | エンジニアリング | シニアエンジニア | tanaka@example.com | ¥7,500,000 | 2020-04-01 |
| 2 | 佐藤花子 | デザイン | UIデザイナー | sato@example.com | ¥6,000,000 | 2021-07-15 |
| 3 | 鈴木一郎 | エンジニアリング | テックリード | suzuki@example.com | ¥9,000,000 | 2019-01-10 |
| 4 | 高橋美咲 | マーケティング | マーケター | takahashi@example.com | ¥5,500,000 | 2022-03-20 |
| 5 | 伊藤健太 | エンジニアリング | フロントエンドエンジニア | ito@example.com | ¥6,500,000 | 2021-11-01 |
| 6 | 渡辺真理 | 人事 | HRマネージャー | watanabe@example.com | ¥7,000,000 | 2018-06-01 |
| 7 | 山本大輔 | デザイン | プロダクトデザイナー | yamamoto@example.com | ¥6,800,000 | 2020-09-15 |
| 8 | 中村さくら | マーケティング | コンテンツディレクター | nakamura@example.com | ¥6,200,000 | 2022-01-10 |
セルをダブルクリックで編集(IDは編集不可)
特徴
- • ヘッドレスUIでスタイルに完全な自由度
- • ソート・フィルタ・ページネーションのロジックを提供
- • バンドルサイズが非常に小さい(~15KB gzipped)
- • TypeScript ファーストで型安全
インストール
npm install @tanstack/react-tabletsx
'use client';
import {
useReactTable,
getCoreRowModel,
flexRender,
type ColumnDef,
} from '@tanstack/react-table';
import { useMemo } from 'react';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
const data: Employee[] = [
{ id: 1, name: '田中太郎', department: 'エンジニアリング', salary: 7500000 },
{ id: 2, name: '佐藤花子', department: 'デザイン', salary: 6000000 },
{ id: 3, name: '鈴木一郎', department: 'マーケティング', salary: 5500000 },
];
export function TanStackTableDemo() {
const columns = useMemo<ColumnDef<Employee>[]>(() => [
{ accessorKey: 'id', header: 'ID' },
{ accessorKey: 'name', header: '氏名' },
{ accessorKey: 'department', header: '部署' },
{
accessorKey: 'salary',
header: '年収',
cell: info => `¥${info.getValue<number>().toLocaleString()}`,
},
], []);
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
return (
<div className="overflow-x-auto border border-gray-200 rounded-lg">
<table className="w-full text-sm">
<thead>
{table.getHeaderGroups().map(hg => (
<tr key={hg.id} className="bg-gray-100 border-b border-gray-200">
{hg.headers.map(h => (
<th key={h.id} className="text-left px-3 py-2.5 font-semibold text-gray-700">
{flexRender(h.column.columnDef.header, h.getContext())}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map(row => (
<tr key={row.id} className="border-b border-gray-100 hover:bg-blue-50">
{row.getVisibleCells().map(cell => (
<td key={cell.id} className="px-3 py-2">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、TanStack Table(@tanstack/react-table)を使った編集可能なデータグリッドを実装してください。 - 使用ライブラリ: @tanstack/react-table(useReactTable、getCoreRowModel、flexRender、ColumnDef) - ColumnDef 型でカラム定義し、useReactTable フックでテーブルを構築すること - セルをダブルクリックしてインライン編集できること(IDカラムは編集不可) - 編集中のセルは input 要素に切り替え、Enter/Escape/blur で確定・キャンセルすること - 数値列(salary)は入力時に number 型の input を使用すること - getHeaderGroups、getRowModel を使ってヘッダーと行をレンダリングすること
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
3. カスタム実装(React + Tailwind CSS)
ライブラリ不要の完全カスタム実装 — 行の追加・削除・ソートも自作
| ID | 氏名 | 部署 | 役職 | メール | 年収 | 入社日 | |
|---|---|---|---|---|---|---|---|
| 1 | 田中太郎 | エンジニアリング | シニアエンジニア | tanaka@example.com | ¥7,500,000 | 2020-04-01 | |
| 2 | 佐藤花子 | デザイン | UIデザイナー | sato@example.com | ¥6,000,000 | 2021-07-15 | |
| 3 | 鈴木一郎 | エンジニアリング | テックリード | suzuki@example.com | ¥9,000,000 | 2019-01-10 | |
| 4 | 高橋美咲 | マーケティング | マーケター | takahashi@example.com | ¥5,500,000 | 2022-03-20 | |
| 5 | 伊藤健太 | エンジニアリング | フロントエンドエンジニア | ito@example.com | ¥6,500,000 | 2021-11-01 | |
| 6 | 渡辺真理 | 人事 | HRマネージャー | watanabe@example.com | ¥7,000,000 | 2018-06-01 | |
| 7 | 山本大輔 | デザイン | プロダクトデザイナー | yamamoto@example.com | ¥6,800,000 | 2020-09-15 | |
| 8 | 中村さくら | マーケティング | コンテンツディレクター | nakamura@example.com | ¥6,200,000 | 2022-01-10 |
ヘッダーをクリックでソート、セルをダブルクリックで編集
特徴
- • 外部ライブラリ不要で依存関係が少ない
- • 行の追加・削除・ソート・インライン編集を自作
- • デザインの自由度が最も高い
- • バンドルサイズへの影響が最小限
インストール
追加パッケージ不要(React + Tailwind CSS のみ)tsx
'use client';
import { useState, useMemo } from 'react';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
const initialData: Employee[] = [
{ id: 1, name: '田中太郎', department: 'エンジニアリング', salary: 7500000 },
{ id: 2, name: '佐藤花子', department: 'デザイン', salary: 6000000 },
{ id: 3, name: '鈴木一郎', department: 'マーケティング', salary: 5500000 },
];
export function CustomGridDemo() {
const [data, setData] = useState(initialData);
const [sortField, setSortField] = useState<keyof Employee | null>(null);
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc');
const sorted = useMemo(() => {
if (!sortField) return data;
return [...data].sort((a, b) => {
const av = a[sortField], bv = b[sortField];
if (typeof av === 'number' && typeof bv === 'number') return sortDir === 'asc' ? av - bv : bv - av;
return sortDir === 'asc' ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av));
});
}, [data, sortField, sortDir]);
const handleSort = (field: keyof Employee) => {
if (sortField === field) setSortDir(d => d === 'asc' ? 'desc' : 'asc');
else { setSortField(field); setSortDir('asc'); }
};
return (
<div className="overflow-x-auto border border-gray-200 rounded-lg">
<table className="w-full text-sm">
<thead>
<tr className="bg-slate-700 text-white">
{(['id', 'name', 'department', 'salary'] as (keyof Employee)[]).map(key => (
<th
key={key}
className="text-left px-3 py-2.5 font-semibold cursor-pointer hover:bg-white/10"
onClick={() => handleSort(key)}
>
{key} {sortField === key ? (sortDir === 'asc' ? '▲' : '▼') : ''}
</th>
))}
</tr>
</thead>
<tbody>
{sorted.map((row, i) => (
<tr key={row.id} className={`border-b border-gray-100 ${i % 2 === 0 ? 'bg-white' : 'bg-gray-50'}`}>
<td className="px-3 py-2">{row.id}</td>
<td className="px-3 py-2">{row.name}</td>
<td className="px-3 py-2">{row.department}</td>
<td className="px-3 py-2">¥{row.salary.toLocaleString()}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、ライブラリ不要のカスタムデータグリッドを実装してください。 - 使用ライブラリ: React + Tailwind CSS のみ(外部グリッドライブラリなし) - セルをダブルクリックしてインライン編集できること(IDカラムは編集不可) - 列ヘッダーをクリックで昇順・降順ソートできること(useMemo でソート済みデータを計算) - 行の追加・削除ができること - 数値列は¥形式で書式化して表示すること - ソート中のカラムには▲▼アイコンを表示すること - 偶数・奇数行で背景色を交互に変えるゼブラストライプを実装すること
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
ライブラリ比較表
| 項目 | AG Grid | TanStack Table | カスタム実装 |
|---|---|---|---|
| インライン編集 | 内蔵(高機能) | 自作(ロジック支援あり) | 自作 |
| ソート | 内蔵 | プラグイン提供 | 自作 |
| フィルタ | 内蔵(多種) | プラグイン提供 | 自作 |
| 仮想スクロール | 内蔵 | 外部ライブラリ併用 | 自作(複雑) |
| バンドルサイズ | 大きめ(~300KB) | 小さい(~15KB) | 最小 |
| 学習コスト | 中〜高 | 中 | 低〜高(要件次第) |
| カスタマイズ性 | 中(テーマ・API) | 高(ヘッドレス) | 最高 |
| おすすめ用途 | 業務アプリ・管理画面 | 独自デザインのテーブル | シンプルな要件 |
まとめ
AG Grid — 業務アプリや管理画面など、大量データを扱う本格的なデータグリッドが必要な場合に最適。ソート・フィルタ・編集・仮想スクロールがすべて内蔵されている。
TanStack Table — 独自のデザインシステムに合わせたテーブルを構築したい場合におすすめ。ロジックだけを提供するヘッドレス設計で、UIの自由度が高い。
カスタム実装 — シンプルな要件やプロトタイプに最適。ライブラリ依存がなく、必要な機能だけを実装できる。