0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

参考対象

  • useSWRって何?という方
  • データ取得にuseEffectを使用している方

インフォメーション
こちらは初歩的な内容になっております。もっと知りたい方は公式ドキュメント等をご覧ください。

useSWRとは

公式ドキュメントから引用します。

“SWR” という名前は、 HTTP RFC 5861(opens in a new tab) で提唱された HTTP キャッシュ無効化戦略である stale-while-revalidate に由来しています。 SWR は、まずキャッシュからデータを返し(stale)、次にフェッチリクエストを送り(revalidate)、最後に最新のデータを持ってくるという戦略です。

つまり、useSWRは特定のデータをキャッシュし、必要に応じてそのデータを返しつつ、バックグラウンドで新しいデータを取得して最新状態を保ちます。

useEffectでデータをフェッチする方法

まずは、useEffectを使ったデータ取得方法を見てみましょう。今回のサンプルコードでは、JSONPlaceholderからユーザーデータを取得し、一覧を表示します。

import axios from "axios";
import { useEffect, useState } from "react";

interface User {
  id: string;
  username: string;
  email: string;
  address: {
    city: string;
  };
}

const api = "https://jsonplaceholder.typicode.com/users";

function App() {
  const [users, setUsers] = useState<User[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setIsLoading(true);
    setError(null);
    const getUser = async () => {
      try {
        const response = await axios.get(api);
        setUsers(response.data);
      } catch (err) {
        setError("Failed to fetch users.");
        console.error(err);
      } finally {
        setIsLoading(false);
      }
    };
    getUser();
  }, []);
  if (error) return <div>{error}</div>;
  if (isLoading) return <div>Loading...</div>;
  return (
    <div className="App">
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            <p>{user.username}</p>
            <p>{user.email}</p>
            <p>{user.address.city}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App

このコードでは、useEffect内でAPIを叩いています。useEffectの第二引数を空配列にしているので、初回マウント時のみ発火します。

コードを見ると、ユーザー情報、ローディング状態、エラー状態を管理するためにuseStateが多く使われています。また、useEffectにはキャッシュのメカニズムがないため、データに変更がない場合でもリロードするたびにデータ取得を行っています。

これらの問題を解決してくれるのが、useSWRです!

useSWRでデータをフェッチする方法

次に、useSWRを使ったデータ取得方法を見てみましょう。

useSWRのデータの取得方法は以下のようになります。(公式ドキュメント参照)

import useSWR from 'swr'
import axios from 'axios'

// fetchを使用した場合
const fetcher = url => fetch(url).then(r => r.json()) // urlはuseSWR()の第一引数で渡されたURL

// axiosを使用した場合
const fetcher = url => axios.get(url).then(res => res.data)

function Profile() {
	const { data, error, isLoading } = useSWR('/api/user', fetcher)
	
	if (error) return <div>failed to load</div>
	if (isLoading) return <div>loading...</div>
	return <div>hello {data.name}!</div>
}

useSWRフックはキー文字列とフェッチ関数を受け取ります。キーはデータの一意な識別子(通常はAPIのURL)で、フェッチ関数に渡されます。フェッチ関数はデータを返す非同期関数で、ネイティブのfetchやAxiosのようなツールを使用できます。

このフックは、リクエストの状態にもとづいて data と isLoading, error の三つの値を返します。

useSWRを使用する利点は以下の通りです。

  • キャッシュにより、同じデータを何度も取得する必要がなく、アプリケーションのレスポンス性能が向上。
  • デフォルトでデータを自動的に再取得する仕組みを持っているため、データが変更された際に自動的に最新の情報を反映可能。
  • 少ないコードで効果的にデータを取得できる。

では、実際にuseSWRを使用してユーザー情報を取得してみましょう!

App.tsx
import { useFetchUser } from './hooks/useFetchUser'

function App() {
  const { data, error, loading } = useFetchUser();
  if (error) {
    console.error(error);
    return (
      <div>Failed to fetch users.</div>
    )
  };
  if (loading) return <div>Loading...</div>
  return (
    <div>
      <ul>
        {data?.map((user) => (
          <li key={user.id}>
            <p>{user.username}</p>
            <p>{user.email}</p>
            <p>{user.address.city}</p>
          </li>
        ))}
      </ul>
    </div>
  )
}

export default App
useFetchUser.ts
import axios from "axios";
import useSWR from "swr";
import { User } from "../type/type";

const fetcher = (url :string) => axios.get(url).then((res) => res.data);
const api = "https://jsonplaceholder.typicode.com/users"

export const useFetchUser = () => {
  const { data, error, isLoading } = useSWR<User[]>(api, fetcher);
  return {
    data,
    error,
    loading: isLoading,
  }
}
TypeScript.ts
export interface User {
  id: number;
  username: string;
  email: string;
  address: {
    city: string;
  };
}

useFetchUserというフックを作成し、そこでAPIを叩いています。取得したdata、error、loadingを返却します。

App.tsxでuseFetchUserからdata、error、loadingを受け取り、エラー時、ローディング時、成功時の処理をしています。

...めっちゃ簡単!記述が凄いシンプルになりました!ステートでの管理がなくなったのでコードも見やすくなりました。

まとめ

今まで「APIを叩く→useEffectを使う!!!」という考えでしたが、これを機にuseSWRを積極的に使ってみようと思います。

間違ってる点などございましたら、ぜひコメントで教えてください。

参考

公式ドキュメント

ブログ

YouTube

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?