Next.js APIを作成してみよう

こんにちは、Yuuichi(@WestHillWorker)です。

今回は、Next.jsにて簡単なAPIを作成して、APIの取得から表示をする部分について進めていこうと思います。

公式サイトを参考にして、天気情報をjsonに保存して、ランダムで取得しブラウザに表示するような流れとなります。

スポンサーリンク

今回作成するもの

http://localhost:3000/

API作成 -> API呼び出し -> 表示処理の順番で作成していきます。

API作成について

まず最初に天気情報を取得できるようなAPIを作成します。

pages/api/wether.jsを作成

APIのRouteは、pages/api内のすべてのファイル対象となるため、api配下にwether.jsを配置します。

export default (req, res) => {
  const wether = {
    wether: "はれ", location: "東京都", temperature: "30℃"
  }
  res.status(200).json(wether);
};

1つ天気を返す簡単なものを作成し、http://localhost:3000/api/wetherにアクセスしてみましょう。

以下のようなデータが取得できると思います。

{“wether":"はれ","location":"東京都","temperature":"30℃"}

天気一覧用のjson作成

1つでも良いのですが、試しにjsonに複数天気情報を記載して、それを元にランダムに天気情報を取得するようにしてみます。

仮にdata/wethers.jsonを作成します。

[
  {
    "wether": "はれ",
    "location": "東京都",
    "temperature": "30℃"
  },
  {
    "wether": "くもり",
    "location": "埼玉県",
    "temperature": "20℃"
  },
  {
    "wether": "あめ",
    "location": "千葉県",
    "temperature": "10℃"
  }
]

wetherのAPIをjsonから取得するように変更します。

// json読み込み
import wethers from '../../data/wethers.json';
export default (req, res) => {
  // jsonの配列から乱数で天気情報を取得
  const wether = wethers[Math.floor(Math.random() * wethers.length)];
  res.status(200).json(wether);
};

ここまででAPIにアクセスするとランダムで結果が変わってくると思います。

API呼び出し準備

swrというライブラリでAPIをコールするため、npmコマンドでインストールします。

$ npm install swr

SWRは、リモートデータのフェッチ用のReact Hooksライブラリで、キャッシュ機構が備わっているとのことです。詳しくは、swrを参照ください。

APIの呼び出しからブラウザ表示

pages/index.jsにて先ほど作成した天気情報APIを呼び出してみましょう。

import useSWR from 'swr';
// 天気のAPIを呼び出して、jsonを返す関数
const fetcher = (url) => {
  return fetch(url).then(r => r.json());
}
const Index = () => {
  // apiへのパスとfetch用の関数を渡します
  const { data, error } = useSWR('/api/wether', fetcher);
  const location = data?.location;
  const temperature = data?.temperature;
  let wether = data?.wether;
  // apiの呼び出し中に表示
  if (!data) wether = 'now Loading...';
  // apiで例外(エラーなどが起きた場合に表示)
  if (error) wether = 'Failed to fetch the wethers.';
  return (
    <main className="center">
      <div className="wether">{wether}</div>
      {location && <div>場所: {location}</div>}
      {temperature && <div>気温: {temperature}</div>}
    </main>
  );
};
export default Index;

useSWRを利用すると戻り値に正常時のdataとAPI側でエラーが発生した際のerrorを返却してくれます。

APIから戻ってくるまでの間は、now Loading的な表示、エラーなどがあった場合は、エラーを表示するような仕組みが備わってます。

ブラウザで確認

$ yarn dev
http://localhost:3000/

ブラウザの更新に応じて、天気情報が変われば完成です!

お疲れ様でした。

ここからは、少し試しにAPIに時間がかかったり、エラーが起きた場合の動作も見てみます。

APIの方でsleepを入れてみましょう

pages/api/wether.jsで3秒間待たせるように修正します。

import wethers from '../../data/wethers.json';
export default (req, res) => {
  function sleep(waitMsec) {
    var startMsec = new Date();
    while (new Date() - startMsec < waitMsec);
  }
  sleep(3000);
  const wether = wethers[Math.floor(Math.random() * wethers.length)];
  res.status(200).json(wether);
};

ブラウザ確認

index.jsで定義していたwether変数のnow Loading…が表示されました。

APIの方でエラーを入れてみましょう

pages/api/wether.jsでエラーをthrowさせるように修正します。

import wethers from '../../data/wethers.json';
export default (req, res) => {
  try {
    throw new Error('エラー発生')
    const wether = wethers[Math.floor(Math.random() * wethers.length)];
    res.status(200).json(wether);
  } catch (e) {
    throw e
  }
};

ちょっと強引ですが、いきなりエラーを投げて、ブラウザで確認してみます。

ブラウザ確認

index.jsで定義していたerrorの戻り値からwether変数のFailed to fetch the wethers.が表示されました。

途中からswrの挙動についての確認になってしまいましたが、APIなどの非同期処理を扱う場合、next.jsとswrの相性がすごく良いんだと思いました。

今回ここまでとなります。ありがとうございました!!