Reactでデータ取得するおすすめの方法はSWRだ!

 React 

 SWR 

 Fetch 

作成日:2022/04/03

はじめに

React で外部 API から情報を取得したいとき、皆さんはどうしていますか?

Fetch API や axios が有名どころだと思います。

しかし、今回オススメするのは「自動的に継続的にデータ更新」をしてくれる Hooks であるSWRについて紹介したいと思います。

この記事の目的

React でデータ取得の各種ライブラリについて知る

Fetch API、axios と SWR の違いとは?

Fetch API

概要

まずは、Fetch API の基本的な使い方を見てみましょう。

export default function Index () {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch("/api/url", {method: "GET"})
    .then(res => res.json())
    .then(resData => setData(resData));
    .catch(error => console.error(error))
  }, []);

  return (
    <ul>
      {data.map(el => <li key={el.id}> {el.title} </li>)}
    </ul>
  );
}

今回は、JSON データを取得し、 setData  data を更新することを想定します。

また、 useEffect の第 2 引数を空配列にして、最初にマウントされる時だけデータを取得するようにしています。

まずは、fetch は

fetch("APIのURL", {各種パラメータ})

を最初に記述します。データ取得は GET メソッドなので、 {method: "GET"} としています。

次に、 then でレスポンスを受け取りますが、ここではまだ JSON データではないので json() を記述する必要があります。

その次の then でデータを state にセットします。

注意点

エラーハンドリングには注意が必要です。

データ取得時にエラーが発生しても、 catch でエラー内容を取得できないことがあります(404 や 500 エラーなど)。

正確にエラーハンドリングするには、 then では以下のようにする必要があります。

.then(res => {
  if(!res.ok) {
    console.error(res)
  } else {
    res.json()
  }
})

axios

続いて、axios の基本的な使い方を見てみましょう。

export default function Index () {
  const [data, setData] = useState([]);

  useEffect(() => {
    axios.get("/api/url")
    .then(res => setData(res.data));
    .catch(error => console.error(error))
  }, []);

  return (
    <ul>
      {data.map(el => <li key={el.id}> {el.title} </li>)}
    </ul>
  );
}

まずは、axios は

axios.get("APIのURL")

を最初に記述します。データ取得は GET メソッドなので、 get() メソッドを使います。

また、返ってくるデータは JSON 形式なのでパースの必要がないので、Fetch API よりもシンプルになります。

さらに、Fetch API のデメリットである 404 や 500 エラー問題も解決でき、エラーの場合は必ず catch 部分の処理が実行されます。

SWR

概要&メリット

さて、本題の SWR です。

こちらは、React フレームワークである Next.js も手がけている Vercel によって開発されています。

SWR は、

まずキャッシュからデータを返す

フェッチリクエストを送る

最後に最新のデータを持ってくる という流れで処理されます。

メリットは以下の通りです。

非同期処理が非常に簡単

高速で軽量

再利用可能

リアクティブな動作

継続的かつ自動的にデータの更新

非同期処理がシンプルになるだけではなく、データのキャッシュ・データ更新も自動に行ってくれる素晴らしいライブラリです。

基本的な使い方

SWR の基本的な使い方をみてみましょう。

const fetcher = url => axios.get(url).then(res => res.data);

export default function Index () {

  const { data, error } = useSWR("/api/url", fetcher);

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;

  return (
    <ul>
      {data.map(el => <li key={el.id}> {el.title} </li>)}
    </ul>
  );
}

まずは fetcher 関数を作成する必要があります。

const fetcher = url => axios.get(url).then(res => res.data);
// fetchでもOK
const fetcher = url => fetch(url).then(res => res.json())

SWR と axios・Fetch API を比較すると言いましたが、正確には SWR でもこれらを使うことになります。

しかし、axios・Fetch API はこの 1 行のみの記述で大丈夫です。

そして、

const { data, error } = useSWR("/api/url", fetcher);

でデータとエラー内容を取得できます。

データを読み込み中の時は、 data  undefined になるので、ローディング中の表示も簡単に実装できます。

再利用可能な関数にする

複数のコンポーネントでデータ取得したいときは、SWR 部分を切り離して関数にできます。

function fetchData () {
  const { data, error } = useSWR(`/api/url`, fetcher)

  return {
    data: data,
    isLoading: !error && !data,
    isError: error
  }
}
const fetcher = url => axios.get(url).then(res => res.data);

export default function Index () {

  const { data, isLoading, isError } = fetchData();

  if (isLoading) return <div>loading...</div>;
  if (isError) return <div>failed to load</div>;

  return (
    <ul>
      {data.map(el => <li key={el.id}> {el.title} </li>)}
    </ul>
  );
}

このように、驚くほど簡単にデータ取得部分を再利用できます。驚くほどです!!(公式も「驚くほど簡単」と言っています ww)

結論

SWR は、Fetch API や axios では複雑になるデータ取得の状態管理が驚くほど簡単に扱えます。

また、複数コンポーネントで SWR でデータ取得してもリクエストは重複しないので、Redux の store に保存したり、props のバケツリレーもする必要がないようですので、ぜひ使ってみてください!