React Hooks ライブラリ「SWR」の Bound Mutate を Next.js で試してみた

2022.01.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

先日、データ取得のための React Hooks ライブラリ「SWR」をNext.jsで試してみました。

今回はこのライブラリのMutation機能の1つ、 Bound Mutate を試してみたいと思います。

そもそも「Mutation」とは?

Mutationとは、日本語で「変化」や「変更」を表す通り、データの更新を行うための仕組みです。

たとえばGraphQLにおいては、Mutationはデータの作成、更新、削除に利用されるそうです。

In GraphQL, mutations are used to create, update, or delete data.

SWRでは、自動でデータの再検証を行ってくれるのですが、これを手動で行いたい場合にmutate関数を利用できます。「データの更新」のために利用できる関数ですね。

SWRのBound Mutate

SWRにはuseSWRConfig()からmutate関数を取得して呼び出す方法と、useSWR()からmutate関数を取得して呼び出す方法があります。

前者は呼び出し時にキーの文字列を指定して利用しますが、後者はuseSWR()で既にキーを指定しているのでキーパラメータは不要となります。

公式サンプルを一部抜粋すると、前者の場合は以下のようなイメージで

const { mutate } = useSWRConfig()
const { data } = useSWR('/api/user', fetcher)
(...snip...)
// ソースを更新するために API にリクエストを送信
await requestUpdateUsername(newName)
(...snip...)
// このキーを使用して再検証(再取得)
mutate('/api/user')

後者の場合は以下のようなイメージで、こちらが「Bound Mutate」と呼ばれています。

const { data, mutate } = useSWR('/api/user', fetcher)
(...snip...)
// ソースを更新するために API にリクエストを送信
await requestUpdateUsername(newName)
(...snip...)
// ローカルデータをすぐに更新し、再検証(再フェッチ)
mutate({ ...data, name: newName })

こちらの方は、useSWRで指定したキーにバインドされているmutateを利用しており、範囲が限定されています。

試してみる

実際に以下のようなコードをNext.jsで試してみます。

pages/swr-mutate.tsx

import type { NextPage } from "next";
import useSWR from "swr";

const getCookieVal = (key: string) => {
  let cookieVal = ((document.cookie + ";").match(key + "=([^¥S;]*)") || [])[1];
  if (!cookieVal) {
    cookieVal = "[Empty]";
  }
  return cookieVal;
};

const clearCookieVal = (key: string) => {
  document.cookie = key + "=; max-age=0";
};

const SWRMutate: NextPage = () => {
  const { data, mutate } = useSWR("foo", getCookieVal, {
    revalidateOnFocus: false,
  });

  const updateCookieVal = (key: string, val: string) => {
    document.cookie = key + "=" + encodeURIComponent(val);
    mutate(val);
  };

  return (
    <div>
      <h2>{data}</h2>
      <button onClick={() => updateCookieVal("foo", "bar")}>Set Cookie</button>
      <button onClick={() => clearCookieVal("foo")}>Clear Cookie</button>
    </div>
  );
};

export default SWRMutate;

このコードでは、Cookieのキーfooに対してデータ取得を行い、画面に表示しています。

Cookieにデータが存在しなかった場合には[Empty]という値を返して表示し、「Set Cookie」ボタンでbarという値を設定、「Clear Cookie」ボタンで値をクリアします。

また、「Set Cookie」ボタンクリック時のイベントではmutateを呼び出してデータ反映を行います。一方で、「Clear Cookie」ボタンのイベントではmutateは呼び出さずに、データ反映を行わないようにしています。

なお、今回のuseSWRの呼び出しにおいてはフォーカス変更時に自動で再検証がされると挙動が分かりづらいので、revalidateOnFocusfalseにすることで再検証がされないようにしています。

初期状態

実際に動かすと、初期状態はこのような感じです。

Cookieが空なので[Empty]という値が表示されています。

mutateの呼び出し

次に「Set Cookie」ボタンをクリックします。

Cookieが設定されて、mutateが呼び出されたのでbarが表示されました。

mutateを呼び出さない場合

最後に「Clear Cookie」ボタンをクリックします。

Cookieがクリアされましたが、今度はmutateを呼び出していないので画面はそのままbarになっていることが分かります。

まとめ

以上、React Hooks ライブラリ「SWR」のBound Mutateを試してみました。

SWRには様々な自動再検証機能があるのですが、検証タイミングを自分で制御したいケースではmutateを活用できると良さそうですね。

どなたかのお役に立てば幸いです。それでは!

参考