examples/react/composable-tables/README.md
This example demonstrates the createTableHook composition pattern for TanStack Table v9, similar to TanStack Form's createFormHook.
createTableHook)The hooks/table.ts file sets up everything in one place:
_features defines which table features are enabledTFeatures already baked inuseTableContext, useCellContext, useHeaderContext - all typed!createAppColumnHelper pre-bound to your featuresBecause TFeatures is baked into the context hooks at creation time, your custom components don't need type annotations:
// components/table-components.tsx
function PaginationControls() {
const table = useTableContext() // TFeatures already known!
return <table.Subscribe selector={(s) => s.pagination}>...</table.Subscribe>
}
Since TFeatures is configured once in createTableHook, the createAppColumnHelper only needs TData:
// TFeatures already bound - only need TData!
const columnHelper = createAppColumnHelper<Person>()
const columns = columnHelper.columns([
columnHelper.accessor('firstName', { header: 'First Name' }),
columnHelper.accessor('age', { header: 'Age' }),
])
Since _features, _rowModels, and default options are configured once in createTableHook, useAppTable only needs columns and data:
const table = useAppTable({
columns,
data, // TData inferred from this
})
Table Components (accessible via table.ComponentName):
PaginationControls - Full pagination UIRowCount - Row count displayTableToolbar - Header with title and actionsCell Components (accessible via cell.ComponentName in AppCell):
TextCell - Generic text rendererNumberCell - Formatted number rendererStatusCell - Status badgeProgressCell - Progress barRowActionsCell - Row action buttons (view, edit, delete)Header Components (accessible via header.ComponentName in AppHeader):
SortIndicator - Sort direction iconColumnFilter - Filter inputFooter Components (accessible via footer.ComponentName in AppFooter):
FooterColumnId - Display the column IDFooterSum - Sum aggregation for numeric columnsThe useAppTable hook returns these wrapper components:
AppTable - Root wrapper providing table contextAppCell - Cell wrapper with pre-bound cellComponentsAppHeader - Header wrapper with pre-bound headerComponentsAppFooter - Footer wrapper with pre-bound headerComponentsAll App wrapper components support an optional selector prop for optimized re-renders:
// Without selector - children is a function receiving the entity
<table.AppCell cell={c}>
{(cell) => <td><cell.TextCell /></td>}
</table.AppCell>
// With selector - children receives both entity and selected state
<table.AppCell cell={c} selector={(state) => state.columnFilters}>
{(cell, filters) => <td>{filters.length} filters</td>}
</table.AppCell>
// AppTable with selector
<table.AppTable selector={(state) => state.pagination}>
{(pagination) => <div>Page {pagination.pageIndex + 1}</div>}
</table.AppTable>
This wraps the children in a Subscribe component for fine-grained reactivity.
src/
├── hooks/
│ └── table.ts # createTableHook setup with features, row models, and components
├── components/
│ ├── cell-components.tsx # TextCell, NumberCell, StatusCell, ProgressCell, RowActionsCell
│ ├── header-components.tsx # SortIndicator, ColumnFilter
│ └── table-components.tsx # PaginationControls, RowCount, TableToolbar
├── main.tsx # App entry point with table component
├── makeData.ts # Mock data generator
└── index.css # Styles
cd examples/react/large-table
pnpm install
pnpm dev