Skip to content

Persistence

Turn grid edits into create / update / delete change-sets with useGridChanges.

The engine is uncontrolled. Opt into useGridChanges to watch edits and get a precise CRUD delta: plain React, separate install.

Open in
All changes saved
NameEmailRole
Preview with Controlled State
Open in
All changes saved
NameEmailRole
Current Grid State
Live view of the grid engine state for demonstration
Focused Cell:None
Editing Cell:None
Selection Anchor:None
Total Rows:2
Is Dirty:No
Dirty Row Ids:0
Failed Row Ids:0
Can Undo / Redo:No / No
Last Commit:None
pnpm dlx shadcn@latest add @niko-table/data-table-grid @niko-table/data-table-grid-changes

Pass the same initialRows you seeded the grid with. Those ids are “existing”; everything else is a create. For a blank import, pass [].

const grid = useDataGrid<Row>({ columnIds, createEmptyRow, initialRows })
const changes = useGridChanges(grid, { initialRows })
changes.isDirty
changes.getChangeSet() // { created, updated, deleted }
changes.reconcile(result)
Member Purpose
dirtyRowIds / isDirty Reactive dirty set
getChangeSet() Precise delta for save
reconcile({ succeededIds, failedIds }) Settle after save
failedRowIds Rows that failed last reconcile
reset(rows?) Re-baseline

Dirtiness is O(1) per keystroke. getChangeSet() is the precise pass (optionally via isEqual so revert-to-original drops from updated).

async function onSave() {
const { created, updated, deleted } = changes.getChangeSet()
const result = await api.bulkSave({ created, updated, deleted })
changes.reconcile({
succeededIds: result.succeededIds,
failedIds: result.failedIds,
})
}

Debounce the network off dirtyRowIds (identity changes only when dirtiness changes):

React.useEffect(() => {
if (!changes.isDirty) return
const t = setTimeout(async () => {
const delta = changes.getChangeSet()
const result = await api.bulkSave(delta)
changes.reconcile(result)
}, 800)
return () => clearTimeout(t)
}, [changes.dirtyRowIds])

Driven by grid.lastCommit: { kind, ids?, seq }. seq advances only on real commits. You can observe it directly for badges or analytics.