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

web-ui-tanstack-table

TanStack Table v8 を活用し、React でテーブル表示に必要なソート、フィルタ、ページネーション、行選択、仮想スクロール、サーバーサイドデータ処理などを効率的に実装できるUI構築を支援するSkill。

📜 元の英語説明(参考)

TanStack Table v8 patterns - useReactTable, column definitions, sorting, filtering, pagination, row selection, virtual scrolling, server-side data

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

一言でいうと

TanStack Table v8 を活用し、React でテーブル表示に必要なソート、フィルタ、ページネーション、行選択、仮想スクロール、サーバーサイドデータ処理などを効率的に実装できるUI構築を支援するSkill。

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

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

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

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

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

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して web-ui-tanstack-table.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → web-ui-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 は、強力なテーブルとデータグリッドを構築するためのヘッドレス UI ライブラリです。型安全な列定義には、useReactTable フックと createColumnHelper を使用します。ツリーシェイキングのために、必要な行モデルのみをインポートしてください(getSortedRowModelgetFilteredRowModel など)。無限再レンダリングを防ぐために、useMemo でデータと列をメモ化してください。サーバーサイドのデータには、manualPaginationmanualSortingmanualFilteringtrue に設定してください。


<critical_requirements>

重要: この Skill を使用する前に

すべてのコードは、CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順、import type、名前付き定数)

(データと列は必ず useMemo でメモ化してください - 不安定な参照は無限再レンダリングを引き起こします)

(型安全な列定義と適切な TValue 推論のために、必ず createColumnHelper<TData>() を使用してください)

(ツリーシェイキングのために、行モデルは明示的にインポートする必要があります - getSortedRowModelgetFilteredRowModel など)

(直接プロパティアクセスには accessorKey を、計算値には明示的な id を持つ accessorFn を必ず使用してください)

(サーバーサイドのデータには、manualPaginationmanualSortingmanualFilteringtrue に設定する必要があります)

</critical_requirements>


自動検出: TanStack Table, @tanstack/react-table, useReactTable, createColumnHelper, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, ColumnDef, column definitions, table state

使用する場合:

  • ソート、フィルタリング、ページネーションを備えたデータテーブルを構築する場合
  • API 統合によるサーバーサイドのデータテーブルを実装する場合
  • 行の選択と展開が可能なテーブルを作成する場合
  • 大規模なデータセットのための仮想スクロールテーブルを構築する場合
  • 列の表示制御と列の順序付けを実装する場合

使用しない場合:

  • インタラクティブな機能のない単純なテーブル (プレーンな HTML テーブルを使用)
  • 20 行未満で、ソート/フィルタリングの必要がないテーブル
  • ユーザーインタラクションのない読み取り専用のデータ表示

カバーする主要なパターン:

  • 型安全なジェネリクスを使用した useReactTable フックの設定
  • columnHelper を使用した列定義
  • ソート、フィルタリング、ページネーション (クライアントサイドおよびサーバーサイド)
  • 行の選択、行の展開、列の表示/非表示
  • 仮想スクロール、列の固定、列のリサイズ

詳細なリソース:


<philosophy>

Philosophy

TanStack Table は ヘッドレス UI ライブラリ です。マークアップやスタイルなしでテーブルのロジックを提供します。これにより、レンダリングを完全に制御しながら、ライブラリがソート、フィルタリング、ページネーションなどの複雑な状態管理を処理します。

コア原則:

  1. ヘッドレスアーキテクチャ - 構築済みのコンポーネントはありません。マークアップとスタイルはあなたが所有します。
  2. 型安全性 - データ型のためのジェネリクスによる完全な TypeScript サポート。
  3. ツリーシェイカブル - 必要なものだけをインポートします。各機能は個別の行モデルです。
  4. フレームワーク非依存 - 同じ API が React、Vue、Solid、Svelte で動作します。
  5. 高性能 - 仮想化サポートにより、大規模なデータセット向けに最適化されています。

なぜヘッドレスなのか?

ヘッドレスアプローチは、TanStack Table が難しい部分 (状態管理、ソートアルゴリズム、ページネーションロジック) を処理し、あなたがプレゼンテーションを制御することを意味します。これは、次の場合に理想的です。

  • 構築済みのコンポーネントに適合しないカスタムテーブルデザインが必要な場合
  • 既存のデザインシステムと統合する場合
  • 最大限のパフォーマンス制御が必要な場合

</philosophy>


<patterns>

コアパターン

パターン 1: 基本的なテーブル設定

useReactTablecreateColumnHelper を使用して、型安全なテーブルを設定します。完全な実装については、examples/core.md を参照してください。

const columnHelper = createColumnHelper<User>();

const columns = useMemo(
  () => [
    columnHelper.accessor("firstName", { header: "First Name" }),
    // 計算値のための accessorFn - id を必ず含める
    columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
      id: "fullName",
      header: "Full Name",
    }),
  ],
  [],
);

const data = useMemo(() => users, [users]);

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getRowId: (row) => row.id,
});

重要: columnsdata の両方をメモ化してください - 不安定な参照は無限再レンダリングを引き起こします。


パターン 2: ソート

getSortedRowModel と制御された状態を使用して、ソートを有効にします。examples/sorting.md を参照してください。

const [sorting, setSorting] = useState<SortingState>([]);

const table = useReactTable({
  data,
  columns,
  state: { sorting },
  onSortingChange: setSorting,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
});

// 列定義内:
columnHelper.accessor("createdAt", {
  header: "Created",
  sortingFn: "datetime", // Date オブジェクトに必要
});

注意: デフォルトのソートでは日付が正しくソートされません。日付の列には sortingFn: "datetime" を使用してください。


パターン 3: フィルタリング

列のフィ

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

TanStack Table Patterns

Quick Guide: TanStack Table is a headless UI library for building powerful tables and datagrids. Use useReactTable hook with createColumnHelper for type-safe column definitions. Import only the row models you need (getSortedRowModel, getFilteredRowModel, etc.) for tree-shaking. Memoize data and columns with useMemo to prevent infinite re-renders. Set manualPagination, manualSorting, manualFiltering to true for server-side data.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST memoize data and columns with useMemo - unstable references cause infinite re-renders)

(You MUST use createColumnHelper<TData>() for type-safe column definitions with proper TValue inference)

(You MUST import row models explicitly - getSortedRowModel, getFilteredRowModel, etc. - for tree-shaking)

(You MUST use accessorKey for direct property access and accessorFn with explicit id for computed values)

(You MUST set manualPagination, manualSorting, manualFiltering to true for server-side data)

</critical_requirements>


Auto-detection: TanStack Table, @tanstack/react-table, useReactTable, createColumnHelper, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, ColumnDef, column definitions, table state

When to use:

  • Building data tables with sorting, filtering, and pagination
  • Implementing server-side data tables with API integration
  • Creating tables with row selection and expansion
  • Building virtual scrolling tables for large datasets
  • Implementing column visibility controls and column ordering

When NOT to use:

  • Simple tables without interactive features (use plain HTML tables)
  • Tables with fewer than 20 rows and no sorting/filtering needs
  • Read-only data display without user interaction

Key patterns covered:

  • useReactTable hook setup with type-safe generics
  • Column definitions with columnHelper
  • Sorting, filtering, pagination (client-side and server-side)
  • Row selection, expanding rows, column visibility
  • Virtual scrolling, column pinning, column resizing

Detailed Resources:


<philosophy>

Philosophy

TanStack Table is a headless UI library - it provides the logic for tables without any markup or styles. This gives you complete control over rendering while the library handles complex state management for sorting, filtering, pagination, and more.

Core Principles:

  1. Headless Architecture - No pre-built components. You own the markup and styling.
  2. Type Safety - Full TypeScript support with generics for data types.
  3. Tree-Shakable - Import only what you use. Each feature is a separate row model.
  4. Framework Agnostic - Same API works across React, Vue, Solid, and Svelte.
  5. Performant - Optimized for large datasets with virtualization support.

Why Headless?

The headless approach means TanStack Table handles the hard parts (state management, sorting algorithms, pagination logic) while you control presentation. This is ideal when:

  • You need custom table designs that don't fit pre-built components
  • You're integrating with an existing design system
  • You need maximum performance control

</philosophy>


<patterns>

Core Patterns

Pattern 1: Basic Table Setup

Set up a type-safe table with useReactTable and createColumnHelper. See examples/core.md for complete implementation.

const columnHelper = createColumnHelper<User>();

const columns = useMemo(
  () => [
    columnHelper.accessor("firstName", { header: "First Name" }),
    // accessorFn for computed values - MUST include id
    columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
      id: "fullName",
      header: "Full Name",
    }),
  ],
  [],
);

const data = useMemo(() => users, [users]);

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getRowId: (row) => row.id,
});

Critical: Memoize both columns and data - unstable references cause infinite re-renders.


Pattern 2: Sorting

Enable sorting with getSortedRowModel and controlled state. See examples/sorting.md.

const [sorting, setSorting] = useState<SortingState>([]);

const table = useReactTable({
  data,
  columns,
  state: { sorting },
  onSortingChange: setSorting,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
});

// In column def:
columnHelper.accessor("createdAt", {
  header: "Created",
  sortingFn: "datetime", // Required for Date objects
});

Gotcha: Dates don't sort correctly with default sort. Use sortingFn: "datetime" for Date columns.


Pattern 3: Filtering

Column filters and global filter with getFilteredRowModel. See examples/filtering.md.

const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const [globalFilter, setGlobalFilter] = useState("");

const table = useReactTable({
  data,
  columns,
  state: { columnFilters, globalFilter },
  onColumnFiltersChange: setColumnFilters,
  onGlobalFilterChange: setGlobalFilter,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
});

Gotcha: Multiple column filters combine with AND logic, not OR. Use global filter or custom logic for OR behavior.


Pattern 4: Pagination

Client-side and server-side pagination with getPaginationRowModel. See examples/pagination.md.

const DEFAULT_PAGE_SIZE = 10;

const [pagination, setPagination] = useState<PaginationState>({
  pageIndex: 0,
  pageSize: DEFAULT_PAGE_SIZE,
});

const table = useReactTable({
  data,
  columns,
  state: { pagination },
  onPaginationChange: setPagination,
  getCoreRowModel: getCoreRowModel(),
  getPaginationRowModel: getPaginationRowModel(),
});

Gotcha: pageIndex is 0-based internally, but many APIs are 1-based. Add 1 when sending to server.


Pattern 5: Row Selection

Single and multi-row selection. See examples/selection.md.

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

const table = useReactTable({
  data,
  columns,
  state: { rowSelection },
  onRowSelectionChange: setRowSelection,
  getCoreRowModel: getCoreRowModel(),
  enableRowSelection: true,
  getRowId: (row) => row.id, // CRITICAL: Stable IDs for selection
});

Critical: Without getRowId, selection uses array indices which break when data is re-ordered or filtered.


Pattern 6: Server-Side Data

Handle server-side pagination, sorting, and filtering. See examples/server-side.md.

const table = useReactTable({
  data: apiData ?? [],
  columns,
  state: { pagination, sorting, columnFilters },
  onPaginationChange: setPagination,
  onSortingChange: setSorting,
  onColumnFiltersChange: setColumnFilters,
  getCoreRowModel: getCoreRowModel(),
  // CRITICAL: All three manual flags for server-side
  manualPagination: true,
  manualSorting: true,
  manualFiltering: true,
  rowCount: totalFromApi,
});

Critical: Do NOT import client-side row models (getSortedRowModel, etc.) with manual*: true - they are redundant.


Pattern 7: Column Visibility

Toggle column visibility. See examples/column-visibility.md.

const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({
  email: false, // Hide by default
});

// In column def - prevent hiding required columns:
columnHelper.accessor("id", { enableHiding: false });

Pattern 8: Expanding Rows

Expandable rows for hierarchical data or detail views. See examples/expanding.md.

const [expanded, setExpanded] = useState<ExpandedState>({});

const table = useReactTable({
  data,
  columns,
  state: { expanded },
  onExpandedChange: setExpanded,
  getCoreRowModel: getCoreRowModel(),
  getExpandedRowModel: getExpandedRowModel(),
  getRowCanExpand: () => true,
});

Pattern 9: Reusable Generic Table Component

Leverage TypeScript generics for a reusable table component. See examples/core.md.

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
}

export function DataTable<TData, TValue>({
  columns,
  data,
}: DataTableProps<TData, TValue>) {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });
  // ... render table
}

Pattern 10: Column Pinning

Keep columns visible during horizontal scroll. See examples/column-pinning.md.

const [columnPinning, setColumnPinning] = useState<ColumnPinningState>({
  left: ["id"],
  right: ["actions"],
});

Critical: Pinning provides state only. You must apply position: sticky and background CSS yourself to prevent content overlap.


Pattern 11: Column Resizing

User-adjustable column widths. See examples/column-resizing.md.

const table = useReactTable({
  data,
  columns,
  columnResizeMode: "onChange", // or "onEnd" for simpler, more performant
  enableColumnResizing: true,
});

Critical: columnResizeMode: "onChange" requires CSS variables pattern and memoized table body for 60fps performance. Use "onEnd" for simpler cases.

</patterns>


<red_flags>

RED FLAGS

High Priority Issues:

  • Missing useMemo on columns/data - Columns or data defined inline without memoization cause infinite re-renders. Must be memoized or defined outside the component.
  • accessorFn without id - Using accessorFn without providing an id causes runtime errors.
  • Missing manualPagination for server-side - Forgetting manualPagination: true when using server-side data causes the table to paginate already-paginated data.
  • Returning JSX from accessorFn - Accessors return primitive values for sorting/filtering. Use the cell option for JSX rendering.

Medium Priority Issues:

  • Not providing rowCount for server-side - Without rowCount or pageCount, the table cannot calculate correct page count.
  • Missing getRowId with selection - Without getRowId, row selection uses array indices which break on sort/filter.
  • Not using flexRender - Manually rendering header/cell values breaks when columnDef uses a function for header/cell.

Gotchas & Edge Cases:

  • Date sorting requires sortingFn: "datetime" - JavaScript dates don't sort correctly by default
  • Column filters are AND, not OR - Multiple column filters combine with AND logic
  • pageIndex is 0-based - Many APIs use 1-based; add 1 when sending to server
  • autoResetPageIndex defaults to true - Page resets to 0 when data changes; set to false for server-side
  • Column pinning requires sticky CSS - TanStack Table provides state only, you apply CSS
  • columnResizeMode: "onChange" needs CSS variables + memoized body for performance
  • Attach getResizeHandler to both onMouseDown and onTouchStart for mobile support
  • Pinning affects column order - Pinning, column ordering, and grouping all reorder columns; pinning happens first
  • Pinned cells need background color - Otherwise scrolling content shows through

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md

(You MUST memoize data and columns with useMemo - unstable references cause infinite re-renders)

(You MUST use createColumnHelper<TData>() for type-safe column definitions with proper TValue inference)

(You MUST import row models explicitly - getSortedRowModel, getFilteredRowModel, etc. - for tree-shaking)

(You MUST use accessorKey for direct property access and accessorFn with explicit id for computed values)

(You MUST set manualPagination, manualSorting, manualFiltering to true for server-side data)

Failure to follow these rules will cause infinite re-renders, TypeScript errors, and incorrect server-side behavior.

</critical_reminders>