Uploading: {{ uploadProgress }}%
```
### Request/Response Transformation
```typescript
const createPet = api.createPet.useMutation(
{},
{
axiosOptions: {
transformRequest: [
(data) => {
// Apply custom transformation before sending
return JSON.stringify({ ...data, timestamp: Date.now() })
},
],
},
},
)
```
### Overriding Options at Call Time
You can override axios options when calling `mutate()` or `mutateAsync()`:
```typescript
const createPet = api.createPet.useMutation(
{},
{
axiosOptions: {
timeout: 5000,
headers: { 'X-Setup-Header': 'setup-value' },
},
},
)
// Override options at call time
await createPet.mutateAsync({
data: { name: 'Fluffy' },
axiosOptions: {
timeout: 10000, // Overrides the 5000 timeout
headers: {
'X-Call-Header': 'call-value', // Additional headers
Authorization: 'Bearer new-token', // Override specific header
},
},
})
```
### Custom Properties
The `AxiosRequestConfigExtended` type supports arbitrary custom properties beyond standard Axios options:
```typescript
const createPet = api.createPet.useMutation(
{},
{
axiosOptions: {
// Standard Axios options
timeout: 5000,
headers: { 'X-Custom-Header': 'value' },
// Custom properties for interceptors or middleware
manualErrorHandling: true,
handledByAxios: false,
customRetryCount: 3,
requestMetadata: {
requestId: 'req-123',
source: 'create-pet',
},
},
},
)
```
### Common Axios Options for Mutations
| Option | Type | Description |
| -------------------- | ------------- | -------------------------------------------------- |
| `headers` | `object` | Custom request headers (useful for auth tokens) |
| `timeout` | `number` | Request timeout in milliseconds |
| `baseURL` | `string` | Override base URL for this request |
| `auth` | `object` | Basic authentication `{ username, password }` |
| `withCredentials` | `boolean` | Include cookies in cross-origin requests |
| `params` | `object` | URL parameters (merged with queryParams) |
| `onUploadProgress` | `function` | Upload progress callback (useful for file uploads) |
| `onDownloadProgress` | `function` | Download progress callback |
| `signal` | `AbortSignal` | Request cancellation |
| `transformRequest` | `array` | Request data transformers |
| `transformResponse` | `array` | Response data transformers |
For more advanced Axios configuration patterns and examples, see [Axios Configuration guide](./08-axios-configuration.md).
## Mutation Options
### Success Handler
```typescript
const createPet = api.createPet.useMutation(
{},
{
onSuccess: (data, variables, context) => {
console.log('Success!', data) // Response data
console.log('Variables:', variables) // Input parameters
console.log('Context:', context) // Mutation context
},
},
)
```
### Error Handler
```typescript
const createPet = api.createPet.useMutation(
{},
{
onError: (error, variables, context) => {
console.error('Error:', error)
console.error('Variables:', variables)
// Show user-friendly error message
alert(`Failed to create pet: ${error.message}`)
},
},
)
```
### Settled Handler
```typescript
const createPet = api.createPet.useMutation(
{},
{
onSettled: (data, error, variables, context) => {
console.log('Mutation completed')
// Always runs, regardless of success or error
},
},
)
```
### Optimistic Updates
```typescript
import { useQueryClient } from '@tanstack/vue-query'
import { api } from './api/init'
const queryClient = useQueryClient()
const petQuery = api.getPet.useQuery({ petId: '123' })
const updatePet = api.updatePet.useMutation(
{ petId: '123' },
{
onMutate: async (variables) => {
// Cancel outgoing queries
await queryClient.cancelQueries({ queryKey: petQuery.queryKey.value })
// Snapshot previous value
const previousPet = queryClient.getQueryData(petQuery.queryKey.value)
// Optimistically update
queryClient.setQueryData(petQuery.queryKey.value, variables.data)
// Return context with snapshot
return { previousPet }
},
onError: (error, variables, context) => {
// Rollback on error
if (context?.previousPet) {
queryClient.setQueryData(petQuery.queryKey.value, context.previousPet)
}
},
},
)
```
## Mutation State
The mutation object provides reactive state properties:
```typescript
const createPet = api.createPet.useMutation()
console.log(createPet.isPending.value) // true while mutation is in progress
console.log(createPet.isSuccess.value) // true if mutation succeeded
console.log(createPet.isError.value) // true if mutation failed
console.log(createPet.error.value) // Error object if mutation failed
console.log(createPet.data.value) // Response data if mutation succeeded
```
## Automatic Cache Management
By default, mutations automatically:
1. **Update cache** - Insert returned data into the cache
2. **Invalidate queries** - Mark matching queries as stale to trigger refetch
3. **Invalidate list queries** - Automatically invalidate list endpoints
```typescript
// Automatic cache management (default)
const createPet = api.createPet.useMutation({ petId: '123' })
// This will:
// 1. Update cache for getPet/123 with returned data
// 2. Invalidate getPet/123 query
// 3. Invalidate listPets query (detected as related list)
```
## Manual Cache Control
### Disable Automatic Invalidation
```typescript
const updatePet = api.updatePet.useMutation(
{ petId: '123' },
{
dontInvalidate: true, // Don't auto-invalidate
dontUpdateCache: true, // Don't auto-update cache
},
)
```
### Specify Operations to Invalidate
```typescript
const createPet = api.createPet.useMutation(
{ petId: '123' },
{
invalidateOperations: ['listPets', 'getUserPets'],
},
)
```
### Manually Refetch Endpoints
```typescript
const petListQuery = api.listPets.useQuery()
const createPet = api.createPet.useMutation(
{ petId: '123' },
{
refetchEndpoints: [petListQuery], // Refetch these endpoints
},
)
```
## Common Mutation Patterns
### Form Submission
```vue