Next.js と TypeScript で、API ルートを学ぶ

TwitterFacebookHatena

TL;DR

この記事では、Next.js と TypeScript を活用し、API ルートの制作とその適用方法について詳しく説明します。API ルートは Next.js アプリケーションの一部で、エンドポイントとして機能します。ここでは、その作成方法と、クライアント側での使用方法を実例を通じて見ていきます。

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

API ルートとは?

そもそも、API ルートとは、何なのか?ということですが、例えば、みなさんがお店で何かを買うとき、まず商品を選んで、レジに持って行き、お金を払って商品をもらいますよね。そのとき、お店の人が何をすべきかを知るために、レジがあるところに行くわけです。この「レジがあるところ」が、API ルートという考え方に似ています。

API ルートは、ウェブサイトやアプリが他のプログラムと「話す」ための特別な場所です。まるでレジのように、何かを要求したり、情報を得たりするための場所と言えます。例えば、あるアプリが天気の情報を必要とするとき、そのアプリは「天気情報の API ルート」に行って、天気の情報を尋ねます。

API ルートは、ウェブサイトやアプリが特定の情報を要求したとき、または何か特定のことをするように要求したときに、どのように応答するかを定義します。API ルートを通じて、ウェブサイトやアプリは他のプログラムやサービスと「会話」をすることができます。

例えば、私たちが天気予報アプリで今日の天気を調べるとき、天気予報アプリは「天気の API ルート」に行って「今日の天気は何ですか?」と尋ね、API ルートは「今日の天気は晴れです」と答えます。このように、API ルートはプログラム同士の会話を可能にしてくれるのです。

Next.js の API ルート

API ルートは、Next.js に内蔵されたサーバーレス関数です。これらの関数は、pages/api ディレクトリ内の .ts ファイルとして配置され、そのファイルパスがエンドポイントの URL となります。このエンドポイントを通じて、データの取得やデータの更新など、クライアントからのリクエストに対応することができます。

わかりやすいように、シンプルなコードで解説します。

export default function handler(req, res) {
  res.status(200).json({ name: 'John Doe' })
}

このコードは、Next.js で API ルートを作成するためのサンプルコードです。

handler のところは、API ルートを定義するための関数(handler)を宣言しています。Next.js はこのような形式の関数を API ルートとして認識します。

関数handlerは 2 つの引数を取ります。

req(request)

これは API ルートへのリクエスト情報を含むオブジェクトで、リクエストに含まれるデータやリクエストの種類(GET、POST など)などを管理します。

res(response)

これはレスポンスを構築するためのオブジェクトで、API ルートからのレスポンスを送る際に用いられます。

res.status(200).json({ name: 'John Doe' })

この行はレスポンスオブジェクト(res)を使って、クライアント(API ルートへのリクエストを行ったエンティティ)にレスポンスを送ります。

res.status(200)は、 HTTP ステータスコード 200 をレスポンスに設定しています。HTTP ステータスコード 200 は、「成功」を意味します。

.json({ name: 'John Doe' }) は、レスポンスの内容を JSON 形式で送ります。この例では、{ name: 'John Doe' }という JSON を送っています。これは、"name"というキーの値として"John Doe"という文字列を持つ JavaScript のオブジェクトを、JSON として送信します。

最後に、関数の宣言を終了します。

以上のように、この API ルートはリクエストを受けると、必ずステータスコード 200 とともに、{ name: 'John Doe' }という JSON 形式のデータを返します。

この形式では、関数が直接エクスポートされているため、別の名前でインポートすることはできません(常に handler として扱われます)。

他にも、シンプルな API ルートを作成しましょう。以下のファイルは pages/api/hello.ts として保存します。

import { NextApiRequest, NextApiResponse } from 'next'

const handler = (req: NextApiRequest, res: NextApiResponse) => {
  res.status(200).json({ text: 'Hello' })
}

export default handler

このコードでは、handler 関数が API ルートを定義しています。この関数は、リクエストオブジェクト (req) とレスポンスオブジェクト (res) を引数に取り、レスポンスのステータスコードを 200 に設定し、レスポンスのボディに JSON を含めます。

処理を分岐させる

次のコードは、API ルートにおいてリクエストの HTTP メソッド(GET、POST、PUT など)によって処理を分岐させている例です。

export default function handler(req, res) {
  if (req.method === 'POST') {
    // Process a POST request
  } else {
    // Handle any other HTTP method
  }
}

1 行目は、API ルートをハンドリングする関数を宣言しています。関数handlerは引数としてリクエストオブジェクトreqとレスポンスオブジェクトresを受け取ります。

2 行目では、リクエストオブジェクトのmethodプロパティを参照し、その値がPOSTであるかどうかを評価しています。HTTP メソッドがPOSTであれば、このifブロック内のコードが実行されます。ここでは「// Process a POST request」のコメントが書かれていますが、実際には POST リクエストを処理する具体的なコードがこの位置に書かれることを期待しています。

逆に、HTTP メソッドがPOSTでなければ、4 行目のelseブロック内のコードが実行されます。この部分では、POST 以外のリクエストメソッド(GET、PUT、DELETE など)を処理するコードが記述されます。

以上のように、この関数は API ルートに送られてきたリクエストの HTTP メソッドによって、適切な処理を行います。これにより、一つの API ルートで複数の HTTP メソッドをハンドリングすることが可能となります。

Routing: API Routes | Next.js

API ルートの実装

それでは、もっと複雑な例を見てみましょう。ユーザー情報を取得する API ルートを作成してみます。新しい API ルートは pages/api/user.ts というパスに保存します。

import { NextApiRequest, NextApiResponse } from 'next'

type User = {
  name: string
  email: string
}

const handler = (req: NextApiRequest, res: NextApiResponse<User>) => {
  if (req.method === 'GET') {
    // ユーザー情報の偽装
    const user: User = {
      name: 'John Doe',
      email: 'john.doe@example.com',
    }

    res.status(200).json(user)
  } else {
    res.setHeader('Allow', ['GET'])
    res.status(405).end(`Method ${req.method} Not Allowed`)
  }
}

export default handler

ここで、User 型を定義し、それを NextApiResponse の型引数として使っています。これにより、この API ルートがユーザー情報を返すことを明示的に示しています。また、この API ルートは GET リクエストのみを許可し、それ以外のメソッドのリクエストに対しては 405 ステータスコードを返します。

Next.js と TypeScript で、API ルートを学ぶ