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
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This skill builds on core and table-features. Read them first for the model pipeline and plugin slots.
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 constconst features = tableFeatures({
columnFilteringFeature,
filteredRowModel: createFilteredRowModel(),
rowSortingFeature,
sortedRowModel: createSortedRowModel(),
rowPaginationFeature,
paginatedRowModel: createPaginatedRowModel(),
})Pass the full client dataset so each stage can process all rows.
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.
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
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
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
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
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.
9e523bc
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.