CtrlK
BlogDocsLog inGet started
Tessl Logo

table-state

Read and own Preact Table v9 state with useTable selectors, selected table.state, table.Subscribe, table.atoms/store, controlled slices, and external Preact Store atoms. Load for snapshot-versus-subscription bugs or state render tuning.

72

Quality

91%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

This skill builds on @tanstack/table-core#core and getting-started. Preact selection resembles React, but imports and store bindings must remain Preact-native.

State Mental Model

TanStack Table is primarily a state coordinator. Keep state internal unless another subsystem needs to read, persist, or drive it. With no initialState, atoms, state, or on[State]Change, the table owns every registered state slice.

  • table.baseAtoms are internal writable atoms initialized from resolved initial state.
  • table.atoms are readonly derived atoms for the active owner of each registered slice.
  • table.store is the readonly flat store assembled from those atoms.
  • table.state contains only the result of the second useTable selector.

Only registered features contribute state and types. If pagination is absent from table.atoms, table.store, table.state, or table options, add rowPaginationFeature; do not cast around the missing API. Keep features, data, and columns stable across renders.

Setup

const table = useTable({ features, columns, data }, (state) => ({
  pagination: state.pagination,
}))
return <output>{table.state.pagination.pageIndex + 1}</output>

The selector determines rerenders and the shape exposed on table.state; omission selects all registered slices.

Core Patterns

Fine-grained Preact subscription

return (
  <table.Subscribe source={table.atoms.rowSelection}>
    {(selection) => <output>{Object.keys(selection).length}</output>}
  </table.Subscribe>
)

External atom ownership

import { useCreateAtom } from '@tanstack/preact-store'
const pagination = useCreateAtom({ pageIndex: 0, pageSize: 20 })
const table = useTable({ features, columns, data, atoms: { pagination } })

Choose State Ownership

Use one owner per slice:

  • Prefer internal state and feature APIs when state is local to the table.
  • Use initialState for starting/reset values; changing it later does not reset current state.
  • Prefer a stable @tanstack/preact-store atom in atoms when state must be shared. Do not pair it with on[State]Change.
  • Use state.<slice> and the matching callback for simple controlled state. Feed the next value back and handle value-or-updater semantics.

External atoms win over external state, which syncs into the internal base atom. Do not use two owners intentionally. The v8 global onStateChange option is gone; control slices individually or subscribe to table.store.

Initialize, Update, and Reset

Use feature methods (setSorting, nextPage, toggleVisibility, toggleSelected) for writes. Write baseAtoms only as a rare low-level escape hatch for internal state; write the external atom when it owns the slice.

table.resetSorting() // reset to table.initialState.sorting
table.resetPagination()
table.resetPagination(true) // reset to the feature default

Slice resets can update an external owner. Core table.reset() only resets internal base atoms. Import types such as PaginationState for one slice and use TableState<typeof features> when a full feature-inferred state type is actually needed.

Common Mistakes

HIGH Reading snapshots as subscriptions

Wrong:

const page = table.store.state.pagination.pageIndex

Correct:

const page = table.state.pagination.pageIndex

Store and atom .get() reads are snapshots; selected table.state or Subscribe connects a Preact render.

Source: packages/preact-table/src/useTable.ts

HIGH Controlling only the callback

Wrong:

useTable({ features, columns, data, onPaginationChange: setPagination })

Correct:

useTable({
  features,
  columns,
  data,
  state: { pagination },
  onPaginationChange: setPagination,
})

The callback must write into the value supplied for that controlled slice.

Source: docs/framework/preact/guide/table-state.md

MEDIUM Narrowing away rendered dependencies

Wrong:

const table = useTable(options, (state) => ({ pagination: state.pagination }))
return table.getSelectedRowModel().rows.length

Correct:

const table = useTable(options, (state) => ({
  pagination: state.pagination,
  rowSelection: state.rowSelection,
}))
return table.getSelectedRowModel().rows.length

If render output depends on selection, the owning render boundary must subscribe to it directly or via Subscribe.

Source: examples/preact/basic-subscribe

API Discovery

Inspect node_modules/@tanstack/preact-table/dist/useTable.d.ts and Subscribe.d.ts; use @tanstack/preact-store rather than React Store hooks.

Repository
TanStack/table
Last updated
First committed

Is this your skill?

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.