Counts the Clouds

useSWRでPromise.allを使って複数のリソースを読み込む
2021.07.21

Next.js
useSWR

barbara-sampaio-0AgcThF72Aw-unsplash.jpg

環境構築

Next.jsのアプリを作成。

% npx create-next-app
 What is your project named? nextjs-useswr-promise-all
Creating a new Next.js app in /Users/same/apps/nextjs-useswr-promise-all.
#...
% cd nextjs-useswr-promise-all

useSWRをインストール。

% yarn add swr

アプリを起動。

% yarn dev

fetcher関数でPromise.allを返す

useSWRフックの第1引数に配列を渡すと、fetcher関数では引数に展開されるので、引数から複数のPromiseを作成してPromise.allで返すようにすれば複数リソースの読み込みに対応できる。

function fetcher(...urls) {
  const f = url => fetch(url).then(r => r.json())
  return Promise.all(urls.map(f))
}

複数の引数の説明はあるものの、こういった使い方については公式の記載はないようだ。

以下のようなカスタムフックを作成。複数の気象予報情報を読み込んでみる。

import useSWR from 'swr'

function fetcher(...urls) {
  const f = url => fetch(url).then(r => r.json())
  return Promise.all(urls.map(f))
}

function useWeatherForecastRepository() {
  const { data, error } = useSWR([
      'https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json',
      'https://www.jma.go.jp/bosai/forecast/data/forecast/140000.json',
      'https://www.jma.go.jp/bosai/forecast/data/forecast/150000.json',
    ],
    fetcher,
  )

  return {
    data: data ? data.flat() : [],
    isLoading: !data && !error,
    isError: error,
  }
}

export default useWeatherForecastRepository

Viewの作成

import useWeatherForecastRepository from '../repositories/useWeatherForecastRepository'

export default function Home() {
  const { data, isLoading, isError } = useWeatherForecastRepository()
  return (
    <div>
      {isLoading ? (
        <div>Loading...</div>
      ) : isError ? (
        <div>Error!</div>
      ) : (
        <div>
          {data.map((d, i) => (
            <div key={i}>{d.reportDatetime} {d.publishingOffice}</div>
          ))}
        </div>
      )}
    </div>
  )
}

出力

2021-07-21T11:00:00+09:00 気象庁
2021-07-21T11:00:00+09:00 気象庁
2021-07-21T11:00:00+09:00 横浜地方気象台
2021-07-21T11:00:00+09:00 横浜地方気象台
2021-07-21T11:00:00+09:00 新潟地方気象台
2021-07-21T11:00:00+09:00 新潟地方気象台

今回の場合、useSWRフックのデータは2次元配列で返ってくるので事前にflat()している。

useSWRフックで複数のリソースを読み込むことができた。