[日本語訳]SWR ドキュメンテーション ミューテーション

## 追記: 2021年6月8日
[SWR公式日本語訳ページ](https://swr.vercel.app/ja)が追加されたので、そちらをご覧ください

このページは [Mutation – SWR](https://swr.vercel.app/docs/mutation)の日本語訳です
SWR日本語訳全体については[SWR 日本語訳](https://qiita.com/tk1024/items/1b8b4eb7cfaa92be6f1a)をご覧ください

# 自動再検証
`mutate(key)` を呼び出すことにより、同じキーを持つすべてのSWRに再検証メッセージをグローバルにブロードキャストできます。

この例は、ユーザーが"ログアウト"ボタンをクリックしたときに、ログイン情報（`<Profile />`内など）を自動的に再取得する方法を示しています。

```tsx

import useSWR, { mutate } from 'swr'

function App () {
  return (
    <div>
      <Profile />
      <button onClick={() => {
        // cookieの期限を設定します
        document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'
        // このキーを使用しているすべてのSWRに再検証するよう伝えます
        mutate('/api/user')
      }}>
        Logout
      </button>
    </div>
  )
}
```

# ミューテーションとPOSTリクエスト
多くの場合、データにローカルミューテーションを適用することは、変更をより速く感じさせるための良い方法です。データのリモートソースを待つ必要はありません。

`mutate` を使用すると、ローカルデータをプログラムで更新しながら、再検証して最終的に最新のデータに置き換えることができます。

```tsx

import useSWR, { mutate } from 'swr'

function Profile () {
  const { data } = useSWR('/api/user', fetcher)

  return (
    <div>
      <h1>My name is {data.name}.</h1>
      <button onClick={async () => {
        const newName = data.name.toUpperCase()
        
        // ローカルデータをすぐに更新しますが、再検証はしません
        mutate('/api/user', { ...data, name: newName }, false)
        
        // APIにリクエストを送信してソースを更新します
        await requestUpdateUsername(newName)
        
        // 再検証(リフレッシュ)をトリガーしてローカルデータが正しいことを確認します
        mutate('/api/user')
      }}>Uppercase my name!</button>
    </div>
  )
}
```

上記の例のボタンをクリックすると、クライアントデータがローカルで更新され、POSTリクエストが送信されてリモートデータが変更され、最新のデータが取得されます（再検証(revalidation)）。

ただし、多くのPOST APIは更新されたデータを直接返すだけなので、再度再検証する必要はありません。 "ローカルミューテート - リクエスト - アップデート "の使用法を示す例を次に示します。

```tsx

mutate('/api/user', newUser, false)      // `false`を使用して再検証なしで`mutate`を使用します
mutate('/api/user', updateUser(newUser)) // `updateUser` はPromiseリクエストで更新されたドキュメントを返します
```

# 現在のデータに基づくミューテート
現在のデータに基づいてデータの一部を更新したい場合があります。

`mutate` を使用すると、現在キャッシュされている値がある場合はそれを受け取る非同期関数を渡して、更新されたドキュメントを返すことができます。

```tsx

mutate('/api/todos', async todos => {
  // ID `1` の todo を更新して完了させましょう。
  // このAPIは更新後のデータを返します
  const updatedTodo = await fetch('/api/todos/1', {
    method: 'PATCH',
    body: JSON.stringify({ completed: true })
  })

  // リストをフィルターして、更新されたアイテムと一緒に返します
  const filteredTodos = todos.filter(todo => todo.id !== '1')
  return [...filteredTodos, updatedTodo]
})
```

# ミューテートから返されたデータ
ほとんどの場合、キャッシュを更新するにはデータが必要です。 データは解決されるか、`mutate` に渡した promise または async 関数から返されます。

この関数は、更新されたドキュメントを返し、`mutate` が対応するキャッシュ値を更新できるようにします。 呼び出すたびに、なんらかのエラーが発生する可能性があります。

```tsx

try {
  const user = await mutate('/api/user', updateUser(newUser))
} catch (error) {
  // ここでユーザー更新中のエラーを処理します
}
```

# バウンドミューテート
`useSWR`によって返されるSWRオブジェクトには、SWRのキーが事前にバインドされている`mutate()`関数も含まれています。

機能的にはグローバル `mutate` 関数と同等ですが、`key` パラメーターは必要ありません。


```tsx

import useSWR from 'swr'
function Profile () {
  const { data, mutate } = useSWR('/api/user', fetcher)
  return (
    <div>
      <h1>My name is {data.name}.</h1>
      <button onClick={async () => {
        const newName = data.name.toUpperCase()
        // APIにリクエストを送信してデータを更新します
        await requestUpdateUsername(newName)
        // すぐにローカルデータを更新して再検証(リフレッシュ)する
        // 注意: useSWRのmutateを使用する場合は、事前にバインドされているためキーは必要ありません。
        mutate({ ...data, name: newName })
      }}>Uppercase my name!</button>
    </div>
  )
}
```