Next.js と TypeScript で、Fetch API を学ぶ

TwitterFacebookHatena

TL;DR

この記事では、Next.js と TypeScript を使用して Fetch API の活用について詳細に解説します。データ取得についても語りますが、主なテーマは Fetch API の効果的な利用方法です。Web 開発の現場で直面する問題を解決するための具体的な実装例を含みます。

開発環境 バージョン
Next.js 13.4.4
TypeScript 5.0.4
Emotion 11.11.0
React 18.2.0

Fetch API の基礎

Fetch API とは、JavaScript の標準的な API で、非同期的にリソースを取得するためのものです。多くの Web API やデータベースと通信するための基本的な方法ですね。Promise をベースに動作していて、非同期操作を管理するためのインターフェースを提供します。

fetch()

fetch()をわかりやすく解説すると、私たちがパソコンやスマホでウェブサイトを見るときに、そのウェブサイトの情報を取ってくるためのツールのようなものです。

例えば、あなたが遊んでいるゲームアプリがあったとしましょう。そのゲームが進行するたびに、スコアやランキングなどの情報を保存しておく場所が必要ですよね。この情報は、ゲームを作った人たちが管理しているコンピュータ(これをサーバーと呼びます)に保存されます。

さて、あなたがゲームの中で新しいハイスコアを出したとしましょう。その情報をサーバーに送り、自分のスコアが他のプレイヤーと比べてどのくらい高いのか(ランキング)を知りたくなりますよね。そのときに使われるのが、この fetch()なのです。

あなたのゲームアプリは fetch()を使ってサーバーに「ハイスコアの情報をください」というリクエストを送ります。すると、サーバーはそのリクエストに応じてハイスコアの情報を返します。その情報をもとに、あなたのゲームアプリはあなたのスコアがどのくらい高いのかを表示できます。

つまり、fetch()は「情報を取ってきてください」というリクエストをサーバーに送り、その結果を受け取る役割を果たすツールと言えます。

以下に fetch() を使ってウェブからデータを取得する非常に簡単な例を示します。

fetch('https://api.example.com/data')
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error('Error:', error))

この例では、fetch() 関数を使って "https://api.example.com/data" という URL からデータを要求しています。fetch() 関数は Promise を返すため、その結果(Response オブジェクト)を then() メソッドで受け取ります。

response.json() は、取得したデータを JSON 形式に変換します。これも Promise を返すため、then() メソッドを再度使って、変換後のデータ(ここでは data)を取り出します。最後に、console.log(data) で取得したデータをコンソールに表示しています。

なお、データ取得や JSON 形式への変換に問題が発生した場合は、catch() メソッドが呼び出され、エラーメッセージが表示されます。

使い所

fetch()関数は、ウェブサイトやウェブアプリケーションで外部の API(他のウェブサービスから提供される機能)を利用する場合や、自身のサーバーからデータを取得する場合に用いられます。以下に具体的な使用例をいくつか挙げてみます。

天気予報 API を利用して天気情報を取得する: 自身のウェブサイトに天気予報を表示したい場合、fetch()を使って天気予報 API から天気情報を取得し、ウェブサイト上に表示することができます。

ブログ投稿のデータを自身のサーバーから取得する: 自身のブログウェブサイトで各ブログ投稿のデータを表示する場合、fetch()を使って自身のサーバーから各投稿のデータを取得し、それをウェブサイト上に表示することができます。

SNS の投稿を一覧表示する: SNS アプリケーションでユーザーの投稿を一覧表示する場合、fetch()を使ってサーバーから投稿データを取得し、それをアプリケーション上に表示することができます。

以上のように、ウェブサービスにおいて、他のサービスや自身のサーバーからデータを取得する必要がある場合に fetch()が活用されます。

Next.js で実装

それでは、Next.js で実装してみましょう。

// ファイル名: components/FetchExample.tsx
import React, { useEffect, useState } from 'react'

type Props = {
  url: string
}

type Data = {
  // your data type here
}

const FetchExample = ({ url }: Props): JSX.Element => {
  const [data, setData] = useState<Data | null>(null)

  useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((data) => setData(data))
  }, [url])

  if (!data) return <div>Loading...</div>

  // Assuming data is an array for this example
  return (
    <ul>
      {data.map((item) => (
        <li>{/* display your data here */}</li>
      ))}
    </ul>
  )
}

このコードを解説しましょう。これは Next.js と TypeScript を用いて Fetch API を活用したデータ取得の一例です。ファイル名 FetchExample.tsx から見て取れる通り、FetchExample というコンポーネントが定義されています。

それでは、コードを一つずつ解説していきましょう。

import React, { useEffect, useState } from 'react'

ここでは React のフック、useStateuseEffect をインポートしています。これらは、それぞれ状態管理と副作用の制御に利用されます。

type Props = {
  url: string
}

type Data = {
  // your data type here
}

ここでは、2 つの型を定義しています。PropsFetchExample コンポーネントが受け取るプロパティの型を表し、Data は取得するデータの型を表します。

const FetchExample = ({ url }: Props): JSX.Element => {
  const [data, setData] = useState<Data | null>(null)

FetchExample コンポーネントが始まります。useState フックを使って data という状態と、それを更新するための setData 関数を定義しています。初期値は null となっています。

useEffect(() => {
  fetch(url)
    .then((response) => response.json())
    .then((data) => setData(data))
}, [url])

useEffect フックを使っています。このフックの中で Fetch API を用いてデータを取得しています。取得したデータは JSON 形式に変換され、その後 setData 関数を用いて data 状態が更新されます。

if (!data) return <div>Loading...</div>

データがまだ取得できていない(つまり、datanull のまま)場合、"Loading..." と表示されることを表します。

// Assuming data is an array for this example
return (
  <ul>
    {data.map((item) => (
      <li>{/* display your data here */}</li>
    ))}
  </ul>
)

最後に、取得したデータをリスト形式で表示しています。ここでは、データが配列であると仮定しています。map メソッドを使って、配列の各要素に対して <li> 要素を生成し、その中に各データを表示します。どのようにデータを表示するかは、データの形式によります。

Fetch API の活用

基本的な Fetch API の使用方法を理解したところで、Next.js と TypeScript の組み合わせて Fetch API を活用する方法について見ていきましょう。

// ファイル名: pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next'

const handler = (req: NextApiRequest, res: NextApiResponse) => {
  res.status(200).json({ name: 'John Doe' })
}

export default handler

上記のコードでは、Next.js の API ルートを作成し、Fetch API から呼び出すことができます。その後、フロントエンドからこの API を呼び出す方法を見ていきます。

// ファイル名: pages/index.tsx
import React, { useEffect, useState } from 'react'

type Data = {
  name: string
}

const Home = () => {
  const [data, setData] = useState<Data | null>(null)

  useEffect(() => {
    fetch('/api/hello')
      .then((response) => response.json())
      .then((data) => setData(data))
  }, [])

  if (!data) return <div>Loading...</div>

  return <div>{data.name}</div>
}

export default Home

高度な Fetch API の使用例

Fetch API をより高度に使う方法について見ていきましょう。ここでは、エラーハンドリングとリトライロジックを追加します。

// ファイル名: utils/fetchWithRetry.ts
async function fetchWithRetry(url: string, retries: number): Promise<any> {
  try {
    const response = await fetch(url)
    const data = await response.json()
    return data
  } catch (error) {
    if (retries === 1) throw error
    return fetchWithRetry(url, retries - 1)
  }
}

export default fetchWithRetry

ここでは、fetchWithRetry 関数を作成し、エラーが発生したときに再試行するロジックを追加しています。これを利用すると、ネットワークの一時的な問題が発生したときでも、アプリケーションが適切に動作するようになります。

Next.js と TypeScript で、Fetch API を学ぶ