Mutations
Execute transactional Convex writes with reactive state, callbacks, and safe results.
useConvexMutation returns a callable function with state attached.
const updateProject = useConvexMutation(api.projects.update)
await updateProject({ projectId, name })State
| Field | Meaning |
|---|---|
status | idle, pending, success, or error |
pending | Whether the latest active call is pending |
data | Result of the latest successful call |
error | Latest committed ConvexCallError |
reset() | Clear data/error and return to idle |
Throwing versus safe
Use the callable when failure is exceptional:
try {
await updateProject({ projectId, name })
} catch (error) {
toast.error(normalizeConvexError(error).message)
}Use .safe() for form-style control flow:
const result = await updateProject.safe({ projectId, name })
if (!result.ok) {
formError.value = result.error
}Callbacks
const createProject = useConvexMutation(api.projects.create, {
onSuccess: (projectId, args) => {
navigateTo(`/projects/${projectId}`)
},
onError: (error, args) => {
reportMutationFailure(args.name, error.kind)
},
})Callback exceptions are logged and ignored. They do not turn a successful server mutation into a failed mutation result.
Live query updates
After the mutation commits, Convex updates affected query subscriptions. Do not call every query's refresh() as a standard mutation step.
Use an optimistic update only when waiting for the confirmed live result creates a meaningful UX problem.
Identity changes
Each call captures the current identity generation. If identity changes before it settles, the call rejects with IDENTITY_CHANGED and does not commit retained UI state under the new user.
The remote mutation may already have committed. Do not automatically retry an identity-changed write.