UNPKG

@tanstack/lit-table

Version:

Headless UI for building powerful tables & datagrids for Lit.

156 lines (110 loc) 6.46 kB
--- name: table-state description: > Use TableController-selected table.state, table.atoms/store, stable table.subscribe selectors, controlled reactive properties plus on*Change, and external TanStack Store atoms. Load when Lit state appears stale, host updates are too broad, or table state must be shared outside the element. metadata: type: framework library: '@tanstack/lit-table' framework: lit library_version: '9.2.4' requires: - '@tanstack/table-core#core' - getting-started sources: - 'TanStack/table:docs/framework/lit/guide/table-state.md' - 'TanStack/table:examples/lit/basic-external-state' - 'TanStack/table:packages/lit-table/src/TableController.ts' --- This skill builds on @tanstack/table-core#core and this package's getting-started skill. ## State Mental Model TanStack Table is primarily a state coordinator. Keep state internal unless another subsystem needs to read, persist, or drive it. Without `initialState`, `atoms`, `state`, or `on[State]Change`, the table owns every registered 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` combines those atoms into one readonly flat store. - `table.state` is only the value selected by the second `controller.table` argument. `TableController` subscribes to state/options and requests host updates. State is feature-based: if pagination is missing from options, atoms, or types, register `rowPaginationFeature`. Keep `features`, `columns`, and `data` references stable across `render()` calls; never create arrays or derive rows inline in the `controller.table` options. ## Setup ```ts import { LitElement, html } from 'lit' import { customElement, state } from 'lit/decorators.js' import { TableController, rowPaginationFeature, tableFeatures, } from '@tanstack/lit-table' import type { PaginationState } from '@tanstack/lit-table' type Item = { id: string } const features = tableFeatures({ rowPaginationFeature }) const columns = [{ accessorKey: 'id' }] const data: Item[] = [{ id: '1' }] @customElement('paged-items') export class PagedItems extends LitElement { @state() private pagination: PaginationState = { pageIndex: 0, pageSize: 10 } private controller = new TableController<typeof features, Item>(this) protected render() { const table = this.controller.table( { features, columns, data, state: { pagination: this.pagination }, onPaginationChange: (updater) => { this.pagination = typeof updater === 'function' ? updater(this.pagination) : updater }, }, (state) => ({ pagination: state.pagination }), ) return html`<button @click=${() => table.nextPage()}> Page ${table.state.pagination.pageIndex + 1} </button>` } } ``` ## Core Patterns ### Read selected render state from table.state The second argument to `controller.table` defines the shape of `table.state`. Its selector should be stable when reused across renders. ### Read one current slice from its atom `table.atoms.pagination.get()` returns the current pagination snapshot. Use it in event handlers; use selected state or `table.subscribe` when a template region must update reactively. ### Put narrow reactive islands in table.subscribe ```ts const page = table.subscribe( table.store, (state) => state.pagination.pageIndex, (pageIndex) => html`<span>Page ${pageIndex + 1}</span>`, ) ``` Keep the selector reference stable for repeated subscription sites. ## Choose State Ownership Use exactly one owner per slice: - Prefer internal state and feature APIs for table-local behavior. - Use `initialState` for starting/reset values. Changing it later does not reset current state. - Prefer a stable external TanStack Store atom in `atoms` when state is shared. Feature APIs write it directly, so omit `on[State]Change`. - Use a reactive host property in `state.<slice>` plus its matching callback for simple controlled state. Write raw values and resolved updater functions back to the property. External atoms take precedence over external `state`, which syncs into the internal base atom. Do not configure multiple owners. The global v8 `onStateChange` option is gone; subscribe to `table.store` if all state changes must be observed. ## Initialize, Update, and Reset Prefer `setSorting`, `nextPage`, `toggleVisibility`, `toggleSelected`, and other feature methods. Direct `baseAtoms` writes are a rare escape hatch for internal state; write the supplied external atom when it owns the slice. ```ts table.resetSorting() table.resetPagination() table.resetPagination(true) ``` Feature resets use `table.initialState` unless `true` requests the feature default and can update external owners. Core `table.reset()` resets internal base atoms only. Use slice types such as `PaginationState` and use `TableState<typeof features>` for the complete feature-inferred state. ## Common Mistakes ### HIGH Callback freezes controlled state Wrong: provide `onPaginationChange` but omit `state.pagination`. Correct: pass the current controlled value and write both direct values and updater functions back to the owning property. An on-change callback marks the slice as externally managed; failing to feed the next value back leaves the table reading the old value. Source: TanStack/table:docs/framework/lit/guide/table-state.md ### HIGH Snapshot read mistaken for subscription Wrong: cache `const page = table.store.state.pagination.pageIndex` outside render and expect it to change. Correct: read selected `table.state` during render or create a `table.subscribe` template island. A store snapshot is current data, not a continuing Lit subscription. Source: TanStack/table:packages/lit-table/src/TableController.ts ### MEDIUM Unstable selector defeats update gating Wrong: create unrelated selector closures throughout the render tree. Correct: define reusable selectors as stable class fields or module functions. TableController shallow-compares selected output; stable selector intent avoids unnecessary subscription churn. Source: TanStack/table:docs/framework/lit/guide/table-state.md ## API Discovery Inspect `node_modules/@tanstack/lit-table/dist/TableController.d.ts`, then `node_modules/@tanstack/table-core/dist/core/table/` for state precedence and updater behavior.