useNexusMutation
useNexusMutation
is a client-side hook for performing “write” operations (e.g., POST, PUT, DELETE). It manages the pending state, result, and provides lifecycle callbacks for side effects like revalidation or showing notifications.
Import
import { useNexusMutation } from "next-nexus/client";
Core Concepts
How It Works
You provide a factory function that takes variables and returns a definition
for a POST, PUT, PATCH, or DELETE request. The hook returns a mutate
function that you can call to trigger the request.
Concurrency Guard
The hook prevents concurrent mutations. If mutate
or mutateAsync
is called while a request is already in-flight, it will throw an error. You should always check the isPending
state to disable UI elements and prevent this.
Lifecycle Callbacks
The options
object accepts several callback functions (onStart
, onSuccess
, onError
, onSettled
) that allow you to run side effects at different stages of the mutation lifecycle. This is the ideal place to perform actions like client-side cache revalidation or optimistic updates.
Signature
Parameters
factory
:(variables: TVariables) => NexusDefinition<TData>
— A function that accepts mutation variables and returns adefinition
.options?
: An optional object to configure the hook. See Options below.
Return Value
An object containing:
data
:TData | undefined
(the data from the last successful mutation)headers
:Headers | undefined
error
:TError | null
isPending
,isSuccess
,isError
:boolean
mutate
:(variables: TVariables) => void
(fire-and-forget)mutateAsync
:(variables: TVariables) => Promise<TData>
reset
:() => void
(resets the hook’s state)
Options
route?
:string
- Proxies the request through a Next.js Route Handler.onStart?
:(variables: TVariables) => TContext | Promise<TContext>
- Fires before the mutation. Can return a context value that is passed to other callbacks.onSuccess?
:(data: TData, variables: TVariables, context?: TContext) => void | Promise<void>
- Fires on success.onError?
:(error: TError, variables: TVariables, context?: TContext) => void | Promise<void>
- Fires on error.onSettled?
:(data?: TData, error?: TError, variables: TVariables, context?: TContext) => void | Promise<void>
- Fires after the mutation succeeds or fails.
Examples
Basic Mutation
Call mutate
with variables to trigger the mutation. Use onSuccess
to revalidate client-side caches.
"use client";
import { useNexusMutation, revalidateClientTags } from "next-nexus/client";
import { productDefinition } from "@/api/productDefinition";
export function LikeButton({ id }: { id: string }) {
const { mutate, isPending } = useNexusMutation(productDefinition.like, {
onSuccess: () => {
// Invalidate and refetch any queries using this tag
revalidateClientTags(["products"]);
},
});
return (
<button onClick={() => mutate(id)} disabled={isPending}>
{isPending ? "Liking…" : "Like"}
</button>
);
}
Using a route
Proxy
Proxy the request through an internal API route instead of calling the external API directly from the client.
"use client";
import { useNexusMutation } from "next-nexus/client";
import { productDefinition } from "@/api/productDefinition";
export function SaveButton({ id, name }: { id: string; name: string }) {
const { mutate, isPending } = useNexusMutation(productDefinition.update, {
route: "/api/internal/save",
});
return (
<button onClick={() => mutate({ id, name })} disabled={isPending}>
Save
</button>
);
}
See also
- Revalidation
- nexusCache (for optimistic updates)