概要
shadcn/ui の Table コンポーネントの使い方について解説します。 このコンポーネントは、React アプリケーションで静的または動的なテーブルを簡単に作成するためのコンポーネントです。
インストール方法
まず、shadcn/ui ライブラリから Table コンポーネントをインストールします。以下のコマンドを使用します。
このコマンドを実行すると、Table コンポーネントが src/components/ui/table.tsx
にインストールされます。
npx shadcn@latest add table
Table コンポーネントの実装
src/components/ui/table.tsx
には以下の複数のコンポーネントが定義されています。
細かい調整は、使用する際に className
を指定するか、このファイルを編集して行います。
- Table:
<table>
に相当 - TableHeader:
<thead>
に相当 - TableBody:
<tbody>
に相当 - TableFooter:
<tfoot>
に相当 - TableRow:
<tr>
に相当 - TableHead:
<th>
に相当 - TableCell:
<td>
に相当 - TableCaption:
<caption>
に相当
文字は背景色の設定は src/index.css
ファイルを編集することで行います。
--muted-foreground
: キャプチャ、ヘッダの文字色--muted
: ホバー、選択した行の背景色
:root {
// ...
--muted-foreground: #6b7280; /* グレー */
--muted: #f9fafb; /* 非アクティブな行の背景色 */
// ...
}
静的なテーブルを作成する
ここでは、Table コンポーネントを使用して静的なテーブルを作成する方法について説明します。 以下は、商品の一覧を表示する簡単なテーブルの例です。
import {
Table,
TableBody,
TableCaption,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
const ProductTable = () => {
return (
<Table>
{/* Caption */}
<TableCaption>商品の一覧</TableCaption>
{/* Header */}
<TableHeader>
<TableRow>
<TableHead>商品名</TableHead>
<TableHead>値段</TableHead>
</TableRow>
</TableHeader>
{/* Body */}
<TableBody>
<TableRow>
<TableCell>商品A</TableCell>
<TableCell className="text-right">¥2,500</TableCell>
</TableRow>
<TableRow>
<TableCell>商品B</TableCell>
<TableCell className="text-right">¥3,000</TableCell>
</TableRow>
<TableRow>
<TableCell>商品C</TableCell>
<TableCell className="text-right">¥1,500</TableCell>
</TableRow>
<TableRow>
<TableCell>商品D</TableCell>
<TableCell className="text-right">¥4,200</TableCell>
</TableRow>
<TableRow>
<TableCell>商品E</TableCell>
<TableCell className="text-right">¥2,800</TableCell>
</TableRow>
</TableBody>
{/* Footer */}
<TableFooter>
<TableRow>
<TableCell>合計</TableCell>
<TableCell className="text-right">¥14,000</TableCell>
</TableRow>
</TableFooter>
</Table>
);
};
export default ProductTable;
次に、このテーブルコンポーネントをアプリケーションに組み込みます。
import ProductTable from "@/product/product-table";
function App() {
return (
<>
<div className="mx-auto px-6 py-12 container">
<ProductTable />
</div>
</>
);
}
export default App;
動的なテーブルを作成する
TanStack Table を使用して、動的なテーブルを作成するサンプルです。
1. TanStack をインストール
npm install @tanstack/react-table
2. カラムの定義
src/payment
ディレクトリを作成し、その配下に以下の 2 つのファイルを作成します。
src/payment/columns.tsx
: カラムの定義src/payment/data.tsx
: テーブルの実装
カラムは、TanStack Table の ColumnDef 型の配列として、定義します。
import { ColumnDef } from "@tanstack/react-table";
export type Payment = {
id: string;
amount: number;
status: "pending" | "processing" | "success" | "failed";
email: string;
};
export const columns: ColumnDef<Payment>[] = [
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "amount",
header: "Amount",
},
];
解説:
データの配列の要素のインタフェースを定義しています。
export type Payment = {
id: string;
amount: number;
status: "pending" | "processing" | "success" | "failed";
email: string;
};
テーブルに表示するカラムの定義を行っています。
accessorKey
: 渡された配列の各要素で、データにアクセスするために使用されるプロパティ名header
: ヘッダの表示名
export const columns: ColumnDef<Payment>[] = [
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "amount",
header: "Amount",
},
];
3. テーブルの実装
次に、動的なテーブルの実装を行います。以下は、src/payment/payment-table.tsx
の内容です。
プロパティとして、カラムの定義 columns
とデータ data
を受け取ります。
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
interface PaymentTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function PaymentTable<TData, TValue>({
columns,
data,
}: PaymentTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
return (
<div className="border rounded-md">
<Table>
{/* Header */}
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
{/* Body */}
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{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">
データなし
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
);
}
解説:
useReactTable
フックを使用して、テーブルを作成します。
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
- API
table.getHeaderGroups()
を使用してヘッダ情報を取得し、テーブルのヘッダを作成します。
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
- API
- HeaderGroup: 複数のヘッダから成るヘッダグループ
- Header: 複数のカラムから成るヘッダ
- Column: カラム
- ColumnDef: カラムの定義
table.getRowModel()
を使用してデータを取得し、テーブルのボディを作成します。
データが存在しない場合は、「データなし」と表示します。
<TableBody>
{table.getRowModel().rows?.length ? (
// データが存在する場合
table.getRowModel().rows.map((row) => (
<TableRow key={row.id} data-state={row.getIsSelected() && "selected"}>
{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">
データなし
</TableCell>
</TableRow>
)}
</TableBody>
コメント