CtrlK
BlogDocsLog inGet started
Tessl Logo

client-vs-server

Choose client or server ownership for filtering, grouping, sorting, expanding, and pagination in TanStack Table v9. Load for manual* flags, mixed pipelines, server counts, or deciding which dataset each row-model stage receives.

66

Quality

80%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

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.

Repository
TanStack/table
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.