mcpField
C
client-vs-server

client-vs-server

github.com/tanstackDevelopment28.5k38 installsUpdated 1w ago
Repository

About client-vs-server

A TanStack Table skill for choosing between client-side and server-side row processing. It explains ownership of filtering, sorting, and pagination, with emphasis on manual-mode behavior and stable data references.

Key features

  1. 01Compare client and server processing pipelines
  2. 02Configure manual filtering, sorting, and pagination
  3. 03Keep data and column references stable
  4. 04Identify common row-model mistakes

Use cases

  1. 01Choose where table filtering and sorting run
  2. 02Implement server-side pagination correctly
  3. 03Prevent repeated row-model invalidation

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/tanstack/table --skill client-vs-server

After installing, type/client-vs-serverin Claude Code to confirm it loaded.

Details

From the project README

This skill builds on core and table-features. Read them first for the model pipeline and plugin slots.

Setup

import {
  rowPaginationFeature,
  rowSortingFeature,
  tableFeatures,
} from '@tanstack/table-core'

export const features = tableFeatures({
  rowSortingFeature,
  rowPaginationFeature,
})
export const serverOptions = {
  manualSorting: true,
  manualPagination: true,
  rowCount: 12_450,
} as const

Core Patterns

Client owns the complete pipeline
const features = tableFeatures({
  columnFilteringFeature,
  filteredRowModel: createFilteredRowModel(),
  rowSortingFeature,
  sortedRowModel: createSortedRowModel(),
  rowPaginationFeature,
  paginatedRowModel: createPaginatedRowModel(),
})

Pass the full client dataset so each stage can process all rows.

Server owns processing
const options = {
  data: serverPage.rows,
  manualFiltering: true,
  manualSorting: true,
  manualPagination: true,
  rowCount: serverPage.total,
}

Put controlled filter, sorting, and pagination state into the request/query key.

Common Mistakes

[CRITICAL] Treating manual flags as requests

Wrong:

const options = { manualSorting: true, data: unsortedRows }

Correct:

const sortedPage = await fetchPage({ sorting })
const options = { manualSorting: true, data: sortedPage.rows }

manualSorting only bypasses client sorting; it never calls a backend.

Source: packages/table-core/src/features/row-sorting/rowSortingFeature.types.ts

[HIGH] Expecting manual pagination to slice

Wrong:

const options = { data: allRows, manualPagination: true }

Correct:

const page = await fetchPage({ pageIndex, pageSize })
const options = {
  data: page.rows,
  manualPagination: true,
  rowCount: page.rowCount,
}

Manual pagination assumes data already represents the intended page. Pass the stable page result directly. If the application deliberately performs custom local slicing instead, derive it with the framework's memo/computed primitive and keep the reference stable until its actual inputs change.

Source: docs/framework/react/guide/pagination.md#manual-server-side-pagination

[HIGH] Sorting only the loaded page accidentally

Wrong:

const options = {
  data: serverPage.rows,
  manualPagination: true,
  manualSorting: false,
}

Correct:

const options = {
  data: serverPage.rows,
  manualPagination: true,
  manualSorting: true,
}

Client sorting can see only loaded rows, so it cannot produce database-wide order.

Source: docs/guide/row-models.md

[HIGH] Recreating processed data or columns inline

Wrong:

const options = {
  data: allRows.filter(matchesFilters).slice(pageStart, pageEnd),
  columns: makeColumns(),
}

Correct:

const processedRows = pageResult.rows
const columns = sharedColumns
const options = { data: processedRows, columns }

data and columns are model inputs. Keep both references stable between meaningful changes with module constants, state, or the adapter's memo/computed primitive; otherwise Table repeatedly invalidates row and column models and some adapters can enter render loops. “Manual” describes processing ownership, not permission to derive new arrays inside table options.

Source: docs/guide/data.md

API Discovery

Inspect node_modules/@tanstack/table-core/dist/core/row-models/coreRowModelsFeature.utils.d.ts for pipeline order and each feature's .types.d.ts for its manual* contract.

Comments

Markdown supported