Mutation Hooks
Mutations are used in GraphQL when the query has some kind of side effect — like logging in, submitting an enquiry, adding an item to a cart, or saving some user data to the server.
Unlike query operations, mutations are never cached on the server.
The naming convention rules still apply to mutation hooks, and mutations should also go in the queries folder.
mutation UseCreateArticle($title: String!) {
createArticle(input: { title: $title }) {
article {
uri
title
}
}
}Mutations which create or update data will, by convention, return the updated object — allowing you to query the new value of the latest object.
Calling Mutations
Unlike query hooks, mutation hooks don’t execute automatically. Instead, you must call .mutate(input) or .mutateAsync(input) to kick off the mutation.
import { useCreateArticle } from '@hooks/queries'
export function CreateArticle() {
const [title, setTitle] = useState('')
const create = useCreateArticle()
if (create.isSuccess) {
return <div>
Article has been created: <Link href={create.data.createArticle.article.uri}>View Article</Link>
</div>
}
return (
<form onSubmit={(e) => {
e.preventDefault()
if (create.isPending) return
// When the form is submitted, kick off the mutation
create.mutate({
title: title
})
}}>
{/* Show an error message, if there is one */}
{create.isError && <p>{create.error.message}</p>}
<input disabled={create.isPending} value={title} onChange={(e) => setTitle(e.currentTarget.title)} />
<button disabled={create.isPending} type="submit">Create Article</button>
</form>
)
}Note that most of the mutations that come with WPGraphQL require WordPress admin privileges, and so the example above will only work correctly if you are logged into WordPress. This doesn’t apply to mutations that you’ve registered yourself.
Hook API
Mutation hooks return an object with the following type:
type UseQuery<T> = {
/* The current status of the query */
status: "pending" | "error" | "success"
/* True if status === 'pending' */
isPending: boolean
/* True if status === 'success' */
isSuccess: boolean
/* True if status === 'error' */
isError: boolean
/* The error object if an error occurred during the query. */
error: QueryError | null
/* The data returned from the server, or `undefined` if the query has not completed yet. */
data: T | undefined
/** Function to trigger the mutation. */
mutate: (args, options?: MutationOptions<T>) => void
/** Function to trigger the mutation, while returning a promise which will either resolve/reject */
mutateAsync: (args, options?: MutationOptions<T>) => Promise<T>
}Options
You can pass the following options to the mutation hook itself, or to mutate or mutateAsync functions:
type MutationOptions<T> = {
/**
* A callback which will be called if the mutation fails.
* This error is also available as `mutation.error` if `mutation.isError` is true.
*/
onError(err: QueryError): void
/**
* A callback which will be called if the mutation succeeds.
* This data is also available as `mutation.data` if `mutation.isSuccess` is true.
*/
onSuccess(data: T)
}Calling Manually
In rare instances, you may want to call a mutation outside of React — like within a Serverless Function, or in a more complex set of functions.
To do this, you can access the mutate method on the hook itself.
import { useCreateArticle } from "@hooks/queries"
async function doSomeStuff() {
const result = await useCreateArticle.mutate({
title: 'My First Article'
})
console.log('The result is', result)
}Most of the time, you should stick to calling mutations using React hooks, since the hook version will handle loading and error states.