SWR 2.0 で追加された useSWRMutation の使い所

こんにちは。GROWI エンジニアの 宮沢 です。今回は便利な React hooks である SWR 2.0 で追加された useSWRMutation の使い所について簡単に紹介しようと思います。ある程度 SWR を使ったことがある人向けの記事となっております。

使い所

「useSWRMutation」とは、手動でデータのミューテーションを行うことができる React Hooks の1つであり、API の POST、PUT、DELETE などの HTTP リクエストをトリガーにして、データの更新を行うことができます。
これにより、ユーザーは任意のタイミングでデータの取得が可能になり、遅延読み込みなどの UX の向上にも繋がります。例えば、1つのページに多数の画像がある場合、1回のレンダリングで全ての画像を読み込んでしまうと読み込みに時間が掛かってしまう可能性があります。そこで、初回レンダリング時にユーザーが視認可能な部分まで画像の読み込みをして、スクロールしたタイミングなどで必要な部分の読み込みをすることで UX の向上が期待できます。このように、遅延読み込みが必要な場合にも、「useSWRMutation」を使って手動でデータの更新を行うことができます。

公式ドキュメント: https://swr.vercel.app/ja/docs/mutation.ja#useswrmutation

従来の useSWR から useSWRMutation でどのような違いがあるのかサンプルコードを使って紹介していきます。

従来の useSWR

page.tsx というサンプルコードを使って見ていきます。page.tsx コンポーネントがレンダリングされるタイミング で useSWRxPage が呼ばれ、fetcher が走りデータが取得されます。

page.tsx

import React, { FC } from 'react';

import useSWR, { SWRResponse } from 'swr';

// swr のカスタムフック
const useSWRxPage = (pageId: string): SWRResponse => {
  const key = pageId;
  return useSWR(
    key, () => fetch('page').then(response => response),
  );
};

type Props = {
  pageId: string,
}

export const Page: FC = (props: Props) => {
  // props から pageId を貰い、カスタムフックの第一引数に入れいている
  const { data, mutate } = useSWRxPage(props.pageId);

  return (
    <>
      <div>
        // ページの本文を表示
        { data.body }
      </div>
        // ボタンを押して再 fetch 
      <button onClick={() => mutate()} />
    </>
  );
};

swr2.0 で追加された useSWRMutation

次に useSWRMutation を使ってみましょう。上記のサンプルコードを useSWR から useSWRMutation を使うコードに置き換えています。useSWRMutation を使うと page.tsx がレンダリングされた時点では fetcher は走りません。trigger と呼ばれる hook を呼び出すことことで初めてミューテーションが行われます。

page.tsx

import React, { FC } from 'react';

import useSWRMutation, { SWRMutationResponse } from 'swr/mutation';

// swr のカスタムフック
const useSWRMUTxPage = (pageId: string): SWRMutationResponse => {
  const key = pageId;
  return useSWRMutation(
    key,
    () => fetch('page').then(response => response),
  );
};

type Props = {
  pageId: string,
}

export const Page: FC = (props: Props) => {
  const { trigger, data } = useSWRMUTxPage(props.pageId);

  return (
    <>
      <div>
        // trigger が実行されるまで undefined
        { data.body }
      </div>
      <button onClick={() => trigger()} />
    </>
  );
};

最後に

useSWRMutation の登場によって SWR を使ったより UX の高いアプリケーション開発が期待できそう..?というお話でした。