[Next.js] getServerSideProps でパラメータを受け取る

2022年2月4日金曜日

Next.js react

t f B! P L

Next.js の GetServerSideProps 関数は、サーバーサイドで実行されるため、router などのクライアント(ブラウザ)に依存するオブジェクトは使用できません。

この記事では、GetServerSideProps でパラメータを受け取る方法を紹介します。

context

まず、GetServerSideProps 関数は、次のように引数を1つとります。

JavaScript の場合

export async function getServerSideProps(context){
	//処理
}

TypeScript の場合

export const getServerSideProps: GetServerSideProps = async (context) => {
	//処理
}

通常 context と名付けるこの変数には、リクエストやレスポンス、クエリパラメータの情報などが格納されています。

params:このページが動的ルートを使用する場合のルートパラメータが含まれます。ページ名が[id].js、の場合、はのparamsようになります{ id: … }。
req:リクエストオブジェクト
res:応答オブジェクト。
query:クエリ文字列を表すオブジェクト。

クエリパラメータを受け取る

GetServerSideProps でクエリパラメータは、引数 contextquery キーに格納されているため、ここから取り出します。

export async function getServerSideProps(context){

  // クエリパラメータの取得
  const keyword = context.query.keyword;
  const page = context.query.page;

  console.log("keyword =", keyword);
  console.log("page =", page);
  return { props: {} };
}

この状態で、http://localhost:3000/pagename?keyword=react&page=2 のような URL でアクセスすると、getServerSideProps の中でパラメータを受け取ることができます。

POST データを受け取る

Next.js の開発で、あまり使用されることはないと思うが、GetServerSideProps で POST パラメータを受け取る場合は、次のように、リクエスト本文を読み取る前に bodyParser を使用して事前に解読しておく必要がある。

解読した後は、普通に req.body.<キー> で POST データにアクセスできる。

import bodyParser from "body-parser";
import { promisify } from "util";

const getBody = promisify(bodyParser.urlencoded());

export async function getServerSideProps({ req, res }) {
  if (req.method === "POST") {
    await getBody(req, res);
  }

  return {
    props: {
      name: req.body?.name || "smeijer",
      message: req.body ? "received!" : "",
    }
  };
}

おまけ(getServerSideProps から API を呼ぶ)

同じサーバーサイドで動く Next.js の API (pages/api の下のやつら)を ServerSideProps から呼び出す方法を紹介しておく。

普通に fetch("http://xxxxx") のように、HTTP リクエストを発行して API を叩いてもいいが、同じサーバー上の処理なのに、わざわざ HTTP で通信するのは無駄である。

ServerSideProps から API を呼び出す場合は、普通に import して呼び出せば良い。

以下は、pages/api/books.ts の API を ServerSideProps から呼び出す例である。

pages/api/books.ts

import type { NextApiRequest, NextApiResponse } from 'next'

// google books api から取得した情報の簡易版インタフェース
export interface Book {
  id: string,
  title: string,
  pageCount: number | null
}

/**
 * Google Books API で鬼滅関連の書籍を検索する関数
 * [GET]/api/books
 * 
 * @returns 見つかった書籍の簡易版リスト
 */
export async function getData() : Promise<Book[]> {
  const response = await fetch("https://www.googleapis.com/books/v1/volumes?q=" + encodeURIComponent("鬼滅"))
  const jsonData = await response.json()
  return jsonData.items.map((elem: any) => {
    return {
      id: elem.id,
      title: elem.volumeInfo.title,
      pageCount: elem.pageCount || null
    }
  });
}

/**
 * Next.js の API 定義
 * 
 * @param req リクエスト
 * @param res レスポンス
 */
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<Book[]>
) {
  const data = await getData();
  res.status(200).json(data);
}

ServerSideProps

import { Book, getData } from  './api/books';

export const getServerSideProps: GetServerSideProps = async (context) => {
  const books: Book[] = await getData();
  return { props: { items: books} };
}
スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ