manual*: true for server-side.state/onXChange vs. external atom: external atom (atoms option) whenever the value needs to be read elsewhere (query key, another component) without forcing the table owner to re-render. Classic state+onXChange for simple, contained cases or v8-migration convenience.useTable vs useAppTable: useAppTable (via createTableHook) as soon as 2+ tables share features/defaults; plain useTable for a genuine one-off.FlexRender vs flexRender: FlexRender/table.FlexRender by default (handles aggregated-cell fallback, placeholder suppression); flexRender() only when you already have the resolved def+context.row/cell/column/header state: always wrap the state-dependent read in Subscribe, scoped to the narrowest slice — required, not optional, under stable-reference props.| Thing | Default |
|---|---|
size / minSize / maxSize (column) | 150 / 20 / Number.MAX_SAFE_INTEGER |
columnResizeMode | 'onEnd' |
pageSize | 10 (typical initialState) |
sortDescFirst | ascending-first for strings, descending-first for numbers |
sortUndefined | 1 (undefined sorts last, ascending) |
enableSortingRemoval | true (cycle includes 'none') |
keepPinnedRows | true (pinned rows stay visible despite filter/pagination) |
paginateExpandedRows | true (sub-rows can span pages) |
| Virtualization threshold (row count where it starts mattering) | thousands+ rows, profile before adopting |
| Worker row models threshold | 100,000+ client-side rows, last resort |
| Feature | Row model factory | Manual flag |
|---|---|---|
columnFilteringFeature | createFilteredRowModel() | manualFiltering |
globalFilteringFeature | (shares filtered row model) | manualFiltering |
rowSortingFeature | createSortedRowModel() | manualSorting |
columnGroupingFeature | createGroupedRowModel() | manualGrouping |
rowExpandingFeature | createExpandedRowModel() | manualExpanding |
rowPaginationFeature | createPaginatedRowModel() | manualPagination |
columnFacetingFeature | createFacetedRowModel() + *MinMaxValues/*UniqueValues | custom factories, no flag |
rowAggregationFeature | (none — pure computation) | manualAggregation |
header nor explicit id.row.index instead of row.getDisplayIndex().row/cell/column/header prop with no Subscribe.autoResetPageIndex: false (and autoResetExpanded: false if expandable).table.Subscribe over columnFilters.manual*: true; reset pageIndex by hand in the change handler.rowSpan={0} rendered as an actual attribute → merges the cell down the whole <tbody>; always skip (return null) instead.filterFn/sortFn: 'myFn' fails to type-check → the function isn't registered in the matching tableFeatures() slot; register it or pass it directly instead of by name.filterFns/sortFns/aggregationFns registry instead of registering individual named functions.