🐥

【React】useEffectとuseSWRをシンプルなコードで比較してみた

に公開

はじめに

useEffectよりシンプルに実装できるuseSWRなるものを知り、どんな違いがあるのか気になったため簡単なコードで両者を比べてみました。

フォルダ&ファイル構成

src/
├── components/
│   ├── UserListEffect.tsx
│   └── UserListSWR.tsx
├── App.tsx
└── index.tsx

サンプルプロジェクトの準備

# プロジェクト作成して移動
npx create-react-app swr-vs-useeffect --template typescript
cd swr-vs-useeffect

# SWRをインポート
npm install swr

ファイルを作成

UserListEffect.tsx
import { useEffect, useState } from 'react';

type User = {
  id: number;
  name: string;
};

export const UserListEffect = () => {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const res = await fetch('https://jsonplaceholder.typicode.com/users');
        if (!res.ok) throw new Error('データ取得失敗');
        const data: User[] = await res.json();
        setUsers(data);
      } catch (err) {
        setError((err as Error).message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, []);

  if (loading) return <p>読み込み中...</p>;
  if (error) return <p>エラー: {error}</p>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

UserListSWR.tsx
import useSWR from 'swr';

type User = {
  id: number;
  name: string;
};

const fetcher = (url: string) => fetch(url).then(res => res.json());

export const UserListSWR = () => {
  const { data, error, isLoading } = useSWR<User[]>(
    'https://jsonplaceholder.typicode.com/users',
    fetcher
  );

  if (isLoading) return <p>読み込み中...</p>;
  if (error) return <p>エラー: {error.message}</p>;

  return (
    <ul>
      {data?.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

ブラウザでの表示

比較まとめ

比較項目 useEffect + fetch useSWR
実装方法 自分でfetch処理を書く 短いコードでOK
エラーハンドリング try-catchで自分で処理 errorが勝手に用意される
キャッシュ なし 自動でキャッシュ
再取得 自分でロジックを書く必要 自動(フォーカス時・ネット復帰時など)
非同期処理の扱い方 async/awaitで自前 useSWR内部でやってくれる

参考

https://ja.react.dev/reference/react/useEffect
https://swr.vercel.app/ja
https://zenn.dev/shtk0119/articles/ab31d5cf5963fe

Discussion