🤔

データ取得にはuseEffectよりuseSWRを使用しよう

2024/03/25に公開

はじめに

データ取得においてuseEffectの副作用を利用してデータ取得を行うものをよく見かけるがuseEffectを利用するよりももっと良い書き方があるのでまとめておきます。

useEffectでよく使用する書き方

'use client';

import { useState, useEffect } from 'react';

interface User {
  id: number
  email: string
  name: string
  username: string
  phone: string
  website: string
}

const Home = () => {
  const [user, setUser] = useState<User | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);

      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/users/1');

        if (!response.ok) {
          throw new Error('Some Error');
        }
        const data = await response.json();
        setUser(data);
      } catch (error: unknown) {
        if (error instanceof Error) {
          setError(error.message);
        }
        setUser(null);
      }
      setIsLoading(false);
    }

    fetchData();
  }, []);

  if (error) return <div>Load is Faild</div>
  if (isLoading) return <div>Loading...</div>

  return (
    <>
      <div>
        <ul>
          <li>お名前:{user?.name}</li>
          <li>メールアドレス:{user?.email}</li>
        </ul>
      </div>
    </>
  )
}

export default Home;

デメリット

  • コードが煩雑になってしまうこと。
    • ロジックが複雑になってしまう。
    • 状態を複数持たないといけない。
    • エラーハンドリングが長文になってしまう。
  • キャッシュができていない。
    • リロードするたびにサーバーからデータを取得している。

※ キャッシュとは、データをブラウザのメモリに一時的に保存することです。キャッシュをすることでブラウザにデータが残っているので毎回サーバーにアクセスすることがなく高速化に繋がる。

useSWRで書くとどうなるのか

'use client';

import useSWR from 'swr';

interface User {
  id: number
  email: string
  name: string
  username: string
  phone: string
  website: string
}

async function fetcher(key: string): Promise<User> {
  return fetch(key).then((response) => response.json());
}

const Home = () => {
  const {data, error, isLoading} = useSWR('https://jsonplaceholder.typicode.com/users/1', fetcher);

  if (error) return <div>Load is Faild</div>
  if (isLoading) return <div>Loading...</div>

  return (
    <>
      <div>
        <ul>
          <li>お名前:{data?.name}</li>
          <li>メールアドレス:{data?.email}</li>
        </ul>
      </div>
    </>
  )
}

export default Home;

メリット

  • コード量が少なくなり可読性が向上。
  • キャッシュがされているので高速化にも繋がる

参考

https://swr.vercel.app/ja
https://www.youtube.com/watch?v=Kb8YbE8NxZ0

Discussion