jpskill.com
🛠️ 開発・MCP コミュニティ

tanstack-table

TanStack Tableは、Reactなど特定のフレームワークに依存せず、データの並び替え、絞り込み、ページ分割、列幅調整など、高度な機能を備えたデータテーブルを柔軟に構築できるSkill。

📜 元の英語説明(参考)

Build powerful data tables with TanStack Table — headless, framework-agnostic table library. Use when someone asks to "build a data table", "TanStack Table", "sortable table", "filterable data grid", "paginated table", "React table", or "headless table library". Covers sorting, filtering, pagination, column resizing, row selection, and virtualization.

🇯🇵 日本人クリエイター向け解説

一言でいうと

TanStack Tableは、Reactなど特定のフレームワークに依存せず、データの並び替え、絞り込み、ページ分割、列幅調整など、高度な機能を備えたデータテーブルを柔軟に構築できるSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o tanstack-table.zip https://jpskill.com/download/15455.zip && unzip -o tanstack-table.zip && rm tanstack-table.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15455.zip -OutFile "$d\tanstack-table.zip"; Expand-Archive "$d\tanstack-table.zip" -DestinationPath $d -Force; ri "$d\tanstack-table.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して tanstack-table.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → tanstack-table フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

TanStack Table

概要

TanStack Table は、ヘッドレスなテーブルライブラリです。ロジック(ソート、フィルタリング、ページネーション、グループ化、列の表示/非表示)を処理し、レンダリングはユーザーが行います。定義済みのスタイルやマークアップはなく、テーブルの外観を完全に制御できます。React、Vue、Svelte、Solid、または vanilla JS で動作します。他の Material UI テーブルと似ていない、カスタムデータテーブルを構築するための標準です。

どのような時に使うか

  • ソート、フィルタリング、ページネーションを備えた表形式のデータを表示する場合
  • テーブルのスタイルを完全に制御する必要がある場合(事前スタイリングされたコンポーネントではない)
  • サーバーサイドのページネーションとフィルタリング
  • 列のサイズ変更、並べ替え、固定を伴う複雑なテーブル
  • 行の選択と一括操作
  • 仮想化されたレンダリングによる大規模なデータセット

手順

セットアップ

npm install @tanstack/react-table

基本的なテーブル

// components/DataTable.tsx — ソート、フィルタリング可能なテーブル
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  flexRender,
  ColumnDef,
  SortingState,
} from "@tanstack/react-table";
import { useState } from "react";

interface User {
  id: number;
  name: string;
  email: string;
  role: string;
  status: "active" | "inactive";
  joinedAt: string;
}

const columns: ColumnDef<User>[] = [
  {
    accessorKey: "name",
    header: "Name",
    cell: (info) => <span className="font-medium">{info.getValue<string>()}</span>,
  },
  { accessorKey: "email", header: "Email" },
  { accessorKey: "role", header: "Role" },
  {
    accessorKey: "status",
    header: "Status",
    cell: (info) => (
      <span className={info.getValue() === "active" ? "text-green-600" : "text-gray-400"}>
        {info.getValue<string>()}
      </span>
    ),
  },
  {
    accessorKey: "joinedAt",
    header: "Joined",
    cell: (info) => new Date(info.getValue<string>()).toLocaleDateString(),
  },
];

export function UsersTable({ 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>
      {/* Search */}
      <input
        value={globalFilter}
        onChange={(e) => setGlobalFilter(e.target.value)}
        placeholder="Search all columns..."
        className="mb-4 p-2 border rounded"
      />

      {/* Table */}
      <table className="w-full border-collapse">
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th
                  key={header.id}
                  onClick={header.column.getToggleSortingHandler()}
                  className="text-left p-3 border-b cursor-pointer hover:bg-gray-50"
                >
                  {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="p-3 border-b">
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>

      {/* Pagination */}
      <div className="flex items-center gap-2 mt-4">
        <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>
          Previous
        </button>
        <span>
          Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
        </span>
        <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
          Next
        </button>
      </div>
    </div>
  );
}

サーバーサイドのページネーション

// components/ServerTable.tsx — API からページごとにデータを取得
const table = useReactTable({
  data: serverData.rows,
  columns,
  pageCount: serverData.pageCount,
  state: { sorting, pagination },
  onSortingChange: setSorting,
  onPaginationChange: setPagination,
  getCoreRowModel: getCoreRowModel(),
  manualPagination: true,   // サーバーがページネーションを処理
  manualSorting: true,      // サーバーがソートを処理
});

// ページネーション/ソートが変更されたときにフェッチ
useEffect(() => {
  fetchData({
    page: pagination.pageIndex,
    pageSize: pagination.pageSize,
    sortBy: sorting[0]?.id,
    sortDir: sorting[0]?.desc ? "desc" : "asc",
  });
}, [pagination, sorting]);

行の選択

const [rowSelection, setRowSelection] = useState({});

const columns: ColumnDef<User>[] = [
  {
    id: "select",
    header: ({ table }) => (
      <input type="checkbox" checked={table.getIsAllRowsSelected()} onChange={table.getToggleAllRowsSelectedHandler()} />
    ),
    cell: ({ row }) => (
      <input type="checkbox" checked={row.getIsSelected()} onChange={row.getToggleSelectedHandler()} />
    ),
  },
  // ... その他の列
];

// 選択された行を取得
const selectedUsers = table.getSelectedRowModel().rows.map((r) => r.original);

例 1: CRUD を備えた管理者データテーブル

ユーザープロンプト: 「ユーザーを管理するための管理者テーブルを作成してください。ソート、フィルタリング、ページネーション、および一括削除を行います。」

エージェントは、すべての機能、一括操作のための行選択、および検索入力を持つ TanStack Table を作成します。

例 2: サーバーサイドでページネーションされたテーブル

ユーザープロンプト: 「私の API はページネーションされたデータを返します。ページごとにデータをフェッチするテーブルを作成してください。」

エージェントは手動ページを設定します

(原文がここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

TanStack Table

Overview

TanStack Table is a headless table library — it handles the logic (sorting, filtering, pagination, grouping, column visibility) and you handle the rendering. No predefined styles or markup, full control over how the table looks. Works with React, Vue, Svelte, Solid, or vanilla JS. The standard for building custom data tables that don't look like every other Material UI table.

When to Use

  • Displaying tabular data with sorting, filtering, and pagination
  • Need full control over table styling (not a pre-styled component)
  • Server-side pagination and filtering
  • Complex tables with column resizing, reordering, and pinning
  • Row selection and bulk actions
  • Large datasets with virtualized rendering

Instructions

Setup

npm install @tanstack/react-table

Basic Table

// components/DataTable.tsx — Sortable, filterable table
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  flexRender,
  ColumnDef,
  SortingState,
} from "@tanstack/react-table";
import { useState } from "react";

interface User {
  id: number;
  name: string;
  email: string;
  role: string;
  status: "active" | "inactive";
  joinedAt: string;
}

const columns: ColumnDef<User>[] = [
  {
    accessorKey: "name",
    header: "Name",
    cell: (info) => <span className="font-medium">{info.getValue<string>()}</span>,
  },
  { accessorKey: "email", header: "Email" },
  { accessorKey: "role", header: "Role" },
  {
    accessorKey: "status",
    header: "Status",
    cell: (info) => (
      <span className={info.getValue() === "active" ? "text-green-600" : "text-gray-400"}>
        {info.getValue<string>()}
      </span>
    ),
  },
  {
    accessorKey: "joinedAt",
    header: "Joined",
    cell: (info) => new Date(info.getValue<string>()).toLocaleDateString(),
  },
];

export function UsersTable({ 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>
      {/* Search */}
      <input
        value={globalFilter}
        onChange={(e) => setGlobalFilter(e.target.value)}
        placeholder="Search all columns..."
        className="mb-4 p-2 border rounded"
      />

      {/* Table */}
      <table className="w-full border-collapse">
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th
                  key={header.id}
                  onClick={header.column.getToggleSortingHandler()}
                  className="text-left p-3 border-b cursor-pointer hover:bg-gray-50"
                >
                  {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="p-3 border-b">
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>

      {/* Pagination */}
      <div className="flex items-center gap-2 mt-4">
        <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>
          Previous
        </button>
        <span>
          Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
        </span>
        <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
          Next
        </button>
      </div>
    </div>
  );
}

Server-Side Pagination

// components/ServerTable.tsx — Fetch data per page from API
const table = useReactTable({
  data: serverData.rows,
  columns,
  pageCount: serverData.pageCount,
  state: { sorting, pagination },
  onSortingChange: setSorting,
  onPaginationChange: setPagination,
  getCoreRowModel: getCoreRowModel(),
  manualPagination: true,   // Server handles pagination
  manualSorting: true,      // Server handles sorting
});

// Fetch when pagination/sorting changes
useEffect(() => {
  fetchData({
    page: pagination.pageIndex,
    pageSize: pagination.pageSize,
    sortBy: sorting[0]?.id,
    sortDir: sorting[0]?.desc ? "desc" : "asc",
  });
}, [pagination, sorting]);

Row Selection

const [rowSelection, setRowSelection] = useState({});

const columns: ColumnDef<User>[] = [
  {
    id: "select",
    header: ({ table }) => (
      <input type="checkbox" checked={table.getIsAllRowsSelected()} onChange={table.getToggleAllRowsSelectedHandler()} />
    ),
    cell: ({ row }) => (
      <input type="checkbox" checked={row.getIsSelected()} onChange={row.getToggleSelectedHandler()} />
    ),
  },
  // ... other columns
];

// Get selected rows
const selectedUsers = table.getSelectedRowModel().rows.map((r) => r.original);

Examples

Example 1: Admin data table with CRUD

User prompt: "Build an admin table for managing users — sort, filter, paginate, and bulk delete."

The agent will create a TanStack Table with all features, row selection for bulk actions, and a search input.

Example 2: Server-side paginated table

User prompt: "My API returns paginated data. Build a table that fetches page by page."

The agent will set up manual pagination/sorting, fetch data on state change, and handle loading states.

Guidelines

  • Headless = you own the markup — style however you want
  • getCoreRowModel is required — always include it
  • Add models for featuresgetSortedRowModel, getFilteredRowModel, etc.
  • manualPagination for server-side — table tracks state, you fetch data
  • ColumnDef for type safetyaccessorKey maps to data fields
  • flexRender for cell rendering — renders header and cell components
  • Row selection with getToggleSelectedHandler — works with checkboxes
  • Column visibilitytable.getColumn("email")?.toggleVisibility(false)
  • Virtualization — combine with @tanstack/react-virtual for 100K+ rows
  • No styles included — use Tailwind, CSS, or any styling solution