UNPKG

@tanstack/table-core

Version:

Headless UI for building powerful tables & datagrids for TS/JS.

165 lines (122 loc) 4.12 kB
--- name: client-vs-server description: > 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. metadata: type: sub-skill library: '@tanstack/table-core' library_version: '9.0.0' requires: ['core', 'table-features'] sources: - 'TanStack/table:docs/guide/row-models.md' - 'TanStack/table:packages/table-core/src/core/row-models/coreRowModelsFeature.utils.ts' - 'TanStack/table:examples/react/with-tanstack-query' --- This skill builds on `core` and `table-features`. Read them first for the model pipeline and plugin slots. ## Setup ```ts 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 ```ts 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 ```ts 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: ```ts const options = { manualSorting: true, data: unsortedRows } ``` Correct: ```ts 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: ```ts const options = { data: allRows, manualPagination: true } ``` Correct: ```ts 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: ```ts const options = { data: serverPage.rows, manualPagination: true, manualSorting: false, } ``` Correct: ```ts 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: ```ts const options = { data: allRows.filter(matchesFilters).slice(pageStart, pageEnd), columns: makeColumns(), } ``` Correct: ```ts 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.