【Next.js】SWRとTanStack Queryの違いを比較

useEffectを使ったデータ取得から脱却し、高速化を図るイケてるライブラリであるよく似た2つ、”SWR”と”TanStack Query”を同じデータの取得を通し、違いの比較をしました。

この記事を見ていただくことで、両者の使い方の違いを知ることができます。

環境

  • next @13.1.1
  • swr @2.0.0
  • tanstack/react-query @4.20.9

SWRとTanStack Queryをなぜ使うのか

両者の比較をする前に、なぜ使う必要があるのですが、それは使った方が良いからです。

以下の2つの使用メリットがあります。

  • キャッシュからデータを返し(stale)、次にフェッチリクエストを送り(revalidate)、最後に最新のデータを持ってくるという処理を行ってくれるため、データの表示時間が短く早い上に、キャッシュを使用するため、余分なリクエストが飛ばないのでコストメリットもある。
  • data と error と isLoading の値を使ってリクエストの現在の状態を判断し、 対応する UI を返すことができるから便利!

実行環境の用意

プロジェクトの作成・起動

% yarn create next-app swr-tanstackquery

% cd swr-tanstackquery

% yarn dev

axiosのinstall。これはデータの取得に使用します。

% yarn add axios

ルートのファイルであるpages/index.tsxのデフォルトの記述を削除します。

mainタグ内を全て消し、SWRとTanStackQueryの2つのcomponentを作ります。

import { Inter } from "@next/font/google";
import Head from "next/head";
import SWRFetch from "../components/swr-fetch";
import TanStackQueryFetch from "../components/tanstack-query-fetch";

const inter = Inter({ subsets: ["latin"] });

export default function Home() {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <SWRFetch />
        <TanStackQueryFetch />
      </main>
    </>
  );
}

これで、実際にコードを書いていくためのベースができました。

SWR

% yarn add swr

SWRFetch componentを作成します。

import useSWR from "swr";
import axios from "axios";

type Album = {
  userId: number;
  id: number;
  title: string;
};

// jsonplaceholderよりデータを取得
const fetchAlbums = async () => {
  const result = await axios.get<Album[]>(
    "https://jsonplaceholder.typicode.com/albums"
  );
  return result.data;
};

const SWRFetch = () => {
  const { data, error, isLoading } = useSWR("/api/album", fetchAlbums);

  if (error) return <p>An error has occurred</p>;

  if (isLoading) return <p>Loading...</p>;

  return (
    <div>
      <p>SWR</p>
      {data?.map((album) => (
        <p key={album.id}>{album.title}</p>
      ))}
    </div>
  );
};

export default SWRFetch;

useSWRの第一引数である”/api/album”は、一意な識別子であり、第二引数の関数に渡されるものです。

TanStack Query

% yarn add @tanstack/react-query

componentの親側とcomponent内の両方に設定を行います。

import { Inter } from "@next/font/google";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import Head from "next/head";
import SWRFetch from "../components/swr-fetch";
import TanStackQueryFetch from "../components/tanstack-query-fetch";

const inter = Inter({ subsets: ["latin"] });

// Create a client
const queryClient = new QueryClient();

export default function Home() {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <SWRFetch />
        {/* Provide the client */}
        <QueryClientProvider client={queryClient}>
          <TanStackQueryFetch />
        </QueryClientProvider>
      </main>
    </>
  );
}

import { useQuery } from "@tanstack/react-query";
import axios from "axios";

type Album = {
  userId: number;
  id: number;
  title: string;
};

// jsonplaceholderよりデータを取得
const fetchAlbums = async () => {
  const result = await axios.get<Album[]>(
    "https://jsonplaceholder.typicode.com/albums"
  );
  return result.data;
};

const TanStackQueryFetch = () => {
  const { isLoading, error, data } = useQuery<Album[]>({
    queryKey: ["album"],
    queryFn: fetchAlbums,
  });

  if (error) return <p>An error has occurred</p>;

  if (isLoading) return <p>Loading...</p>;

  return (
    <div>
      <p>TanStack Query</p>
      {data?.map((album) => (
        <p key={album.id}>{album.title}</p>
      ))}
    </div>
  );
};

export default TanStackQueryFetch;

まとめ

両者の記述方法は、ほとんど同じです。

TanStack Queryのcomponentの親側にも設定記述が必要なことから、やや記述量が多いですが、働き、記述ともにほとんど差がないことがわかりました。

今回取り上げたSWR、TanStack Queryは、ReactのhooksであるSuspenseを使っても一部代替可能です。

それについては以下記事にまとめていますのでご覧ください。

以上、お読みいただきありがとうございました。

コメント