Tablecraft
API Reference

State hooks

Granular, standalone state hooks for composing your own useReactTable call instead of using useTable.

For advanced setups where you compose your own useReactTable call directly, each piece of useTable's state is available as a standalone hook. Each returns state plus setters compatible with TanStack Table's state and on*Change props.

import {
  usePaginationState,
  useSortState,
  useFilterState,
  useColumnFilterState,
  useRowSelectionState,
  useColumnVisibilityState,
  useColumnPinningState,
  useRowExpansionState,
  useGroupingState,
} from '@marvinackerman/tablecraft'

const pagination = usePaginationState({ pageSize: 25 })
const sorting = useSortState({ defaultSort: [{ id: 'createdAt', desc: true }] })
const globalFilter = useFilterState()
const columnFilters = useColumnFilterState()
const rowSelection = useRowSelectionState()
const columnVisibility = useColumnVisibilityState({ defaultVisibility: { id: false } })
const columnPinning = useColumnPinningState()
const rowExpansion = useRowExpansionState({ allowMultiple: false })
const grouping = useGroupingState({ defaultGrouping: ['department'] })

usePaginationState

function usePaginationState(options?: PaginationOptions): {
  state: PaginationState
  onPaginationChange: Dispatch<SetStateAction<PaginationState>>
  setPageIndex: (index: number) => void
  setPageSize: (size: number) => void
  nextPage: () => void
  previousPage: () => void
}

PaginationOptions: { pageSize?: number, pageIndex?: number }

useSortState

function useSortState(options?: SortingOptions): {
  state: SortingState
  onSortingChange: Dispatch<SetStateAction<SortingState>>
  clearSorting: () => void
}

SortingOptions: { defaultSort?: SortingState }

useFilterState

function useFilterState(defaultValue?: string): {
  state: string
  onGlobalFilterChange: Dispatch<SetStateAction<string>>
  clear: () => void
}

Takes a plain string default — not an options object.

useColumnFilterState

function useColumnFilterState(defaultState?: ColumnFiltersState): {
  state: ColumnFiltersState
  onColumnFiltersChange: Dispatch<SetStateAction<ColumnFiltersState>>
  setFilter: (columnId: string, value: unknown) => void
  clearFilter: (columnId: string) => void
  clearAll: () => void
}

Takes a ColumnFiltersState default directly — not an options object.

useRowSelectionState

function useRowSelectionState(options?: UseRowSelectionOptions): {
  state: RowSelectionState
  onRowSelectionChange: Dispatch<SetStateAction<RowSelectionState>>
  toggleRow: (rowId: string) => void
  toggleAll: (rowIds: string[]) => void
  clearSelection: () => void
  selectedRowIds: string[]
  selectedCount: number
  isSelected: (rowId: string) => boolean
  enableMultiRowSelection: boolean
}

UseRowSelectionOptions: { defaultSelection?: RowSelectionState, enableMultiRowSelection?: boolean }

Note: toggleAll here takes the full array of row IDs ((rowIds: string[]) => void) — unlike useTable's rowSelection.toggleAll(), which takes no arguments because it already has the table's rows in scope.

useColumnVisibilityState

function useColumnVisibilityState(options?: UseColumnVisibilityOptions): {
  state: VisibilityState
  onColumnVisibilityChange: Dispatch<SetStateAction<VisibilityState>>
  toggleColumn: (columnId: string) => void
  showColumn: (columnId: string) => void
  hideColumn: (columnId: string) => void
  showAll: () => void
  hiddenColumns: string[]
}

UseColumnVisibilityOptions: { defaultVisibility?: VisibilityState }

useColumnPinningState

function useColumnPinningState(options?: ColumnPinningOptions): {
  state: ColumnPinningState
  setState: Dispatch<SetStateAction<ColumnPinningState>>
  pinLeft: (id: string) => void
  pinRight: (id: string) => void
  unpin: (id: string) => void
  clearPinning: () => void
  isPinned: (id: string) => 'left' | 'right' | false
  leftColumns: string[]
  rightColumns: string[]
}

ColumnPinningOptions: { defaultPinning?: ColumnPinningState }

useRowExpansionState

function useRowExpansionState(options?: UseRowExpansionOptions): {
  state: ExpandedState
  onExpandedChange: OnChangeFn<ExpandedState>
  toggleRow: (rowId: string) => void
  expandRow: (rowId: string) => void
  collapseRow: (rowId: string) => void
  clearExpansion: () => void
  expandedRowIds: string[]
  isExpanded: (rowId: string) => boolean
}

UseRowExpansionOptions (granular-hook form): { defaultExpanded?: ExpandedState, allowMultiple?: boolean }. allowMultiple defaults to true; set false so expanding a new row collapses all others.

Note: useTable's rowExpansion option accepts a wider RowExpansionOptions that also includes paginateExpandedRows and getSubRows (for nested sub-rows) — those two extra fields are not part of this standalone hook's options.

useGroupingState

function useGroupingState(options?: UseGroupingOptions): {
  state: GroupingState
  onGroupingChange: OnChangeFn<GroupingState>
  toggleGrouping: (columnId: string) => void
  setGrouping: (cols: GroupingState) => void
  clearGrouping: () => void
  isGrouped: (columnId: string) => boolean
  groupedColumns: GroupingState
}

UseGroupingOptions: { defaultGrouping?: GroupingState, manualGrouping?: boolean, groupedColumnMode?: false | 'reorder' | 'remove' }

On this page