---
# System prepended metadata

title: React mutation query

---

## React query mutation
### Mutation用於新增/更新/刪除
```
function App() {
  const mutation = useMutation({
    mutationFn: (newTodo) => {
      return axios.post('/todos', newTodo)
    },
  })

  return (
    <div>
      {mutation.isLoading ? (
        'Adding todo...'
      ) : (
        <>
          {mutation.isError ? (
            <div>An error occurred: {mutation.error.message}</div>
          ) : null}

          {mutation.isSuccess ? <div>Todo added!</div> : null}

          <button
            onClick={() => {
              mutation.mutate({ id: new Date(), title: 'Do Laundry' })
            }}
          >
            Create Todo
          </button>
        </>
      )}
    </div>
  )
}
```
### Mutation狀態
> 每個 useMutation 間的 state 是獨立的，保有各自的狀態

* ### isIdle - mutation未被執行且沒有其他狀態時，當reset時狀態也將變為Idle
* ### isLoading - mutation request過程
* ### isSuccess - mutation成功
* ### isError - mutation失敗

###  Mutation reset
> ### reset會將error, data清空，mutation狀態將為Idle
```
const CreateTodo = () => {
  const [title, setTitle] = useState('')
  const mutation = useMutation({ mutationFn: createTodo })

  const onCreateTodo = (e) => {
    e.preventDefault()
    mutation.mutate({ title })
  }

  return (
    <form onSubmit={onCreateTodo}>
      {mutation.error && (
        <h5 onClick={() => mutation.reset()}>{mutation.error}</h5>
      )}
      <input
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <br />
      <button type="submit">Create Todo</button>
    </form>
  )
}
```

### Mutation useIsMutating
> ### useIsMutating()可以取得mutating數量
> https://codesandbox.io/p/sandbox/react-query-shared-status-forked-593x7y?file=%2Fsrc%2FApp.tsx
```
function ComponentA() {
  const { mutate } = useMutation(mutationFn, {
    mutationKey: 'mutationKey'
  });

  const handleClick = () => {
    mutate();  // invoke the mutation
  }

  return (/* ... */)
}

// get the mutation state from another component
function App() {

  // the useIsMutating will return the number that is mutating
  const isMutating = !!useIsMutating('mutationKey');

  return (
    <button disabled={isMutating}>Save</button>
  )
}
```

### Side effect
```
useMutation({
  mutationFn: addTodo,
  
  //I will fire first
  onSuccess: (data, variables, context) => {
    // Trigger when mutation is successful 
  },
  onError: (error, variables, context) => {
    // Trigger when mutation is fail
  },
  onSettled: (data, error, variables, context) => {
    // Trigger when mutation is successful or fail
  },
})

mutate(todo, {
  // I will fire second
  onSuccess: (data, variables, context) => {
    // ...
  },
  onError: (error, variables, context) => {
    // ...
  },
  onSettled: (data, error, variables, context) => {
    // ...
  },
})
```

### Invalidate queries
> ### invalidateQueries()會將所有的query狀態標記為stale
```
// Invalidate every query in the cache
queryClient.invalidateQueries()

// Invalidate every query with a key that starts with `todos`
queryClient.invalidateQueries({
  queryKey: ['todos'],
  //Exactly match queryKey
  exact: true,
})

// The query below will be invalidated
const todoListQuery = useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodoList,
})

// However, the following query below will NOT be invalidated
const todoListQuery = useQuery({
  queryKey: ['todos', { type: 'done' }],
  queryFn: fetchTodoList,
})

import { useMutation, useQueryClient } from '@tanstack/react-query'

const queryClient = useQueryClient()

// When this mutation succeeds, invalidate any queries with the `todos` query key
const mutation = useMutation({
  mutationFn: addTodo,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
})
```