> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/TanStack/query/llms.txt
> Use this file to discover all available pages before exploring further.

# createMutation

> Solid primitive for performing mutations and side effects

Perform mutations and side effects with the `createMutation` primitive. It provides methods to trigger mutations and tracks their state reactively in SolidJS.

## Signature

```ts theme={null}
function createMutation<TData, TError, TVariables, TContext>(
  options: Accessor<CreateMutationOptions<TData, TError, TVariables, TContext>>,
  queryClient?: Accessor<QueryClient>,
): CreateMutationResult<TData, TError, TVariables, TContext>
```

## Parameters

<ParamField path="options" type="Accessor<CreateMutationOptions<TData, TError, TVariables, TContext>>" required>
  A Solid accessor (function) returning mutation configuration options.

  <Expandable title="properties">
    <ParamField path="mutationFn" type="(variables: TVariables) => Promise<TData>" required>
      The function that performs the mutation.
    </ParamField>

    <ParamField path="onMutate" type="(variables: TVariables) => Promise<TContext> | TContext">
      Called before mutation executes. Useful for optimistic updates. Return context value.
    </ParamField>

    <ParamField path="onSuccess" type="(data: TData, variables: TVariables, context: TContext) => void">
      Called when mutation succeeds.
    </ParamField>

    <ParamField path="onError" type="(error: TError, variables: TVariables, context: TContext | undefined) => void">
      Called when mutation fails.
    </ParamField>

    <ParamField path="onSettled" type="(data: TData | undefined, error: TError | null, variables: TVariables, context: TContext | undefined) => void">
      Called when mutation completes (success or error).
    </ParamField>

    <ParamField path="retry" type="number | boolean">
      Number of retry attempts or boolean to enable/disable retries.
    </ParamField>

    <ParamField path="retryDelay" type="number | ((attemptIndex: number) => number)">
      Delay between retry attempts.
    </ParamField>

    <ParamField path="throwOnError" type="boolean">
      Throw errors instead of setting error state.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="queryClient" type="Accessor<QueryClient>">
  Accessor returning a custom QueryClient instance. If not provided, uses the client from context.
</ParamField>

## Returns

<ResponseField name="CreateMutationResult<TData, TError, TVariables, TContext>" type="object">
  Reactive mutation state and methods.

  <Expandable title="properties">
    <ResponseField name="mutate" type="(variables: TVariables, options?: MutateOptions) => void">
      Trigger the mutation. Fire-and-forget style (doesn't return a promise).
    </ResponseField>

    <ResponseField name="mutateAsync" type="(variables: TVariables, options?: MutateOptions) => Promise<TData>">
      Trigger the mutation and return a promise.
    </ResponseField>

    <ResponseField name="data" type="TData | undefined">
      The mutation result data.
    </ResponseField>

    <ResponseField name="error" type="TError | null">
      The error object if the mutation failed.
    </ResponseField>

    <ResponseField name="isPending" type="boolean">
      `true` when the mutation is currently executing.
    </ResponseField>

    <ResponseField name="isSuccess" type="boolean">
      `true` when the mutation has succeeded.
    </ResponseField>

    <ResponseField name="isError" type="boolean">
      `true` when the mutation has failed.
    </ResponseField>

    <ResponseField name="isIdle" type="boolean">
      `true` when the mutation is idle (not executing).
    </ResponseField>

    <ResponseField name="status" type="'idle' | 'pending' | 'error' | 'success'">
      The current status of the mutation.
    </ResponseField>

    <ResponseField name="variables" type="TVariables | undefined">
      The variables passed to the mutation.
    </ResponseField>

    <ResponseField name="reset" type="() => void">
      Reset the mutation state to initial values.
    </ResponseField>
  </Expandable>
</ResponseField>

## Type Parameters

* `TData` - Type of data returned by the mutation
* `TError` - Type of error (defaults to `DefaultError`)
* `TVariables` - Type of variables passed to the mutation (defaults to `void`)
* `TContext` - Type of context returned by `onMutate` (defaults to `unknown`)

## Examples

### Basic Usage

```tsx theme={null}
import { createMutation, useQueryClient } from '@tanstack/solid-query'
import { Show } from 'solid-js'

function CreateTodo() {
  const queryClient = useQueryClient()

  const mutation = createMutation(() => ({
    mutationFn: async (newTodo) => {
      const res = await fetch('/api/todos', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(newTodo),
      })
      return res.json()
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  }))

  const handleCreate = () => {
    mutation.mutate({ title: 'New Todo', completed: false })
  }

  return (
    <div>
      <button onClick={handleCreate} disabled={mutation.isPending}>
        {mutation.isPending ? 'Adding...' : 'Add Todo'}
      </button>
      <Show when={mutation.isError}>
        <div>Error: {mutation.error?.message}</div>
      </Show>
    </div>
  )
}
```

### With TypeScript

```tsx theme={null}
import { createMutation } from '@tanstack/solid-query'

interface Todo {
  id: number
  title: string
  completed: boolean
}

interface CreateTodoVariables {
  title: string
  completed: boolean
}

function CreateTodo() {
  const mutation = createMutation(() => ({
    mutationFn: async (variables: CreateTodoVariables): Promise<Todo> => {
      const res = await fetch('/api/todos', {
        method: 'POST',
        body: JSON.stringify(variables),
      })
      return res.json()
    },
  }))

  // Type-safe mutation call
  const handleCreate = () => {
    mutation.mutate({ title: 'Learn Solid Query', completed: false })
  }

  return <button onClick={handleCreate}>Create</button>
}
```

### Optimistic Updates

```tsx theme={null}
import { createMutation, useQueryClient } from '@tanstack/solid-query'

function UpdateTodo() {
  const queryClient = useQueryClient()

  const mutation = createMutation(() => ({
    mutationFn: updateTodo,
    onMutate: async (updatedTodo) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({ queryKey: ['todos'] })
      
      // Snapshot previous value
      const previousTodos = queryClient.getQueryData(['todos'])
      
      // Optimistically update cache
      queryClient.setQueryData(['todos'], (old) => {
        return old.map(todo => 
          todo.id === updatedTodo.id ? updatedTodo : todo
        )
      })
      
      // Return context with snapshot
      return { previousTodos }
    },
    onError: (err, updatedTodo, context) => {
      // Rollback on error
      if (context?.previousTodos) {
        queryClient.setQueryData(['todos'], context.previousTodos)
      }
    },
    onSettled: () => {
      // Always refetch after error or success
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  }))

  return <div>{/* ... */}</div>
}
```

### Using mutateAsync

```tsx theme={null}
import { createMutation } from '@tanstack/solid-query'

function CreateTodo() {
  const mutation = createMutation(() => ({
    mutationFn: createTodo,
  }))

  const handleSubmit = async () => {
    try {
      const newTodo = await mutation.mutateAsync({ title: 'New Todo' })
      console.log('Created todo:', newTodo)
      // Navigate or show success message
    } catch (error) {
      console.error('Failed to create todo:', error)
    }
  }

  return <button onClick={handleSubmit}>Submit</button>
}
```

### Per-Mutation Callbacks

```tsx theme={null}
import { createMutation } from '@tanstack/solid-query'

function CreateTodo() {
  const mutation = createMutation(() => ({
    mutationFn: createTodo,
  }))

  const handleCreate = () => {
    mutation.mutate(
      { title: 'New Todo' },
      {
        onSuccess: (data) => {
          console.log('Created:', data)
        },
        onError: (error) => {
          console.error('Failed:', error)
        },
      }
    )
  }

  return <button onClick={handleCreate}>Create</button>
}
```

### Reset Mutation State

```tsx theme={null}
import { createMutation } from '@tanstack/solid-query'
import { Show } from 'solid-js'

function CreateTodo() {
  const mutation = createMutation(() => ({
    mutationFn: createTodo,
  }))

  const handleCreate = () => {
    mutation.reset() // Reset previous state
    mutation.mutate({ title: 'New Todo' })
  }

  return (
    <div>
      <button onClick={handleCreate}>Create</button>
      <Show when={mutation.isSuccess}>
        <div>Successfully created!</div>
      </Show>
    </div>
  )
}
```

### Multiple Mutations

```tsx theme={null}
import { createMutation, useQueryClient } from '@tanstack/solid-query'

function TodoActions() {
  const queryClient = useQueryClient()

  const createMutation = createMutation(() => ({
    mutationFn: createTodo,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  }))

  const deleteMutation = createMutation(() => ({
    mutationFn: deleteTodo,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  }))

  return (
    <div>
      <button 
        onClick={() => createMutation.mutate({ title: 'New' })}
        disabled={createMutation.isPending}
      >
        Create
      </button>
      <button 
        onClick={() => deleteMutation.mutate(1)}
        disabled={deleteMutation.isPending}
      >
        Delete
      </button>
    </div>
  )
}
```

### Error Handling with Retry

```tsx theme={null}
import { createMutation } from '@tanstack/solid-query'

function CreateTodo() {
  const mutation = createMutation(() => ({
    mutationFn: createTodo,
    retry: 3,
    retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
    onError: (error) => {
      console.error('Mutation failed after retries:', error)
    },
  }))

  return <div>{/* ... */}</div>
}
```

### Reactive Mutation Options

```tsx theme={null}
import { createSignal, createMemo } from 'solid-js'
import { createMutation } from '@tanstack/solid-query'

function CreateTodo() {
  const [shouldRetry, setShouldRetry] = createSignal(true)

  const mutationOptions = createMemo(() => ({
    mutationFn: createTodo,
    retry: shouldRetry() ? 3 : 0,
  }))

  const mutation = createMutation(mutationOptions)

  return <div>{/* ... */}</div>
}
```

### Mutation with Loading State

```tsx theme={null}
import { createMutation } from '@tanstack/solid-query'
import { Show, Switch, Match } from 'solid-js'

function CreateTodo() {
  const mutation = createMutation(() => ({
    mutationFn: createTodo,
  }))

  return (
    <div>
      <button onClick={() => mutation.mutate({ title: 'New' })}>
        Create Todo
      </button>
      
      <Switch>
        <Match when={mutation.isPending}>
          <div>Creating...</div>
        </Match>
        <Match when={mutation.isError}>
          <div>Error: {mutation.error?.message}</div>
        </Match>
        <Match when={mutation.isSuccess}>
          <div>Todo created successfully!</div>
        </Match>
      </Switch>
    </div>
  )
}
```

## Notes

<Note>
  The options parameter must be an accessor (function) to integrate with SolidJS reactivity system.
</Note>

<Tip>
  Use `mutate` for fire-and-forget operations and `mutateAsync` when you need to await the result or handle errors with try/catch.
</Tip>

<Warning>
  Always invalidate or update relevant queries after a successful mutation to keep your UI in sync with the server state.
</Warning>

## Related

* [createQuery](/api/solid/create-query) - For fetching data
* [Mutations Guide](/concepts/mutations) - Detailed guide on mutations
