Skip to content

Table state and editing

Choose who controls table state, where data operations run, and how edits become saved records.

Controlled sorting

Control a state slice when it must synchronize with a URL, server query or another view. Pass both its current value and change handler; handle TanStack's updater function as well as direct values. initialState seeds internal state once. Do not use it as a second owner for a controlled slice.

controlled-table.tsx

Outside Ghost's subscribed renderers, use table.Subscribe or TanStack's selector hooks for reactive reads. Adding an engine feature does not add its surrounding controls: compose those in the application.

Use the same instance in a grid

Pass table to DataGrid to retain the same data, accessor and feature configuration. columnDef.meta.dataGrid adds editable, validate, renderEditor, or other grid policies. The grid adapts the instance's current row model and visible/pinned columns; avoid keeping a parallel filtered row list. Instance mode binds supported sorting, sizing, order and visibility methods; supplied callbacks also receive the requests.

For a small editable collection, the convenience API takes stable { id, data } rows. Every edit callback carries a string draft, including edits to numeric columns; parse and validate it before updating your domain model.

editable-sources.tsx

The grid owns focus, selection and the current edit draft. renderEditor receives that draft plus onChange, commit and cancel; use those commands rather than creating a second edit store. onEditStateChange exposes a snapshot for surrounding feedback. onCellEdit is a synchronous request, not an awaited save transaction. For asynchronous saves, keep pending/error state in the host, preserve the previous record for rollback and reject stale responses by record/revision. Editing UI does not establish write permission.

Client and server data

Client sorting/filtering/pagination operates on the rows supplied to the instance. For server operations, use the matching manualSorting, manualFiltering or manualPagination option and return already processed data; set server row/page counts as appropriate. Control the relevant slices and include them in your request key. Do not apply a client row model to only the current server page and describe it as sorting the entire dataset.

Abort or ignore superseded requests. Decide whether off-page selections persist and resolve selected IDs against your backend before an operation. Stable IDs do not imply that an off-page row is loaded. Reordering requests are meaningful only when the application allows an ordering independent of the current sort/filter.

Boundaries and escape routes

The raw convenience grid reports sort/hide/reorder requests to the caller; it does not silently perform domain operations. It also does not expose every TanStack feature option. Switch to a caller-owned instance when you need filtering, pagination or broader engine configuration. Neither view implements a formula engine, remote cache, transaction manager or automatic server pagination. Grid rendering is not a promise of row virtualization: bound the rendered data through paging or a separately designed virtual composition.

See Data grid API, Table API, and TanStack controlled state.