Skip to content

useMutate

import { useMutate } from '@xnetjs/react'
import { TaskSchema } from './schema'
function AddTaskButton() {
const { create, isPending } = useMutate()
return (
<button
disabled={isPending}
onClick={() =>
create(TaskSchema, {
title: 'New task',
status: 'todo'
})
}
>
{isPending ? 'Creating...' : 'Add Task'}
</button>
)
}
function useMutate(): UseMutateResult

Takes no parameters. Returns methods for all mutation operations.

MethodSignatureDescription
create(schema, data, id?) => Promise<FlatNode | null>Create a new node. Returns the created node or null if store isn’t ready.
update(schema, id, data) => Promise<FlatNode | null>Update properties. Only changed fields are written.
remove(id) => Promise<void>Soft-delete a node. Recoverable via restore.
restore(id) => Promise<FlatNode | null>Restore a soft-deleted node.
mutate(ops[]) => Promise<MutateResult | null>Execute a batch of operations through the active data bridge.
FieldTypeDescription
isPendingbooleantrue if any mutation is currently in flight.
pendingCountnumberNumber of concurrent mutations in flight.
const { create, update, remove, restore } = useMutate()
// Create
const task = await create(TaskSchema, {
title: 'Ship v1',
status: 'todo'
})
// Update (sparse — only changed fields)
await update(TaskSchema, task.id, { status: 'doing' })
// Soft-delete
await remove(task.id)
// Restore
await restore(task.id)

Pass an optional third argument to create to specify the node ID:

const task = await create(TaskSchema, { title: 'Known ID' }, 'my-custom-id')
// task.id === 'my-custom-id'

Use mutate() to execute multiple operations in one call:

const { mutate } = useMutate()
const result = await mutate([
{ type: 'create', schema: TaskSchema, data: { title: 'Task A' } },
{ type: 'create', schema: TaskSchema, data: { title: 'Task B' } },
{ type: 'update', id: existingId, data: { status: 'done' } },
{ type: 'delete', id: oldTaskId }
])
interface MutateResult {
results: (NodeState | null)[] // One result per operation (null for deletes)
}
function TaskForm({ taskId }: { taskId: string }) {
const { data: task } = useQuery(TaskSchema, taskId)
const { update } = useMutate()
const [title, setTitle] = useState('')
useEffect(() => {
if (task) setTitle(task.title)
}, [task])
const save = () => update(TaskSchema, taskId, { title })
return (
<form
onSubmit={(e) => {
e.preventDefault()
save()
}}
>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<button type="submit">Save</button>
</form>
)
}
const { create, isPending, pendingCount } = useMutate()
// Disable UI during mutations
<button disabled={isPending}>Save</button>
// Show count for batch operations
{pendingCount > 0 && <span>{pendingCount} operations pending...</span>}
  • useQuery — read the data you mutate
  • useNode — alternative for single-node editing with Yjs
  • defineSchema — define the schemas you write to