【Next.js】 microCMSで問い合わせ機能を実装してみた

おはこんにちばんは。Next.js + microCMSで問い合わせ機能を実装してみました。

はじめに

  • 実装方法について触れています。特にAPIキーを隠蔽せずに実装している記事が見受けられてたので、その辺は注意して触れていきます。
  • Next.js や microCMSとは?っといった概要には触れません。


microCMSの設定

この辺は他のサイトで触れてるところがあったので雑に説明します。

コンテンツ(API)の追加

API名とエンドポイントを入力し、コンテンツ(API)を追加します。



続いて、POSTが使えるリスト形式を選択します。



必要なAPIスキーマーを設定すれば終了です。



なお、以下も忘れずに実施ください。

  1. POSTリクエストを有効にする(API設定 > HTTPメソッド設定)
  2. APIリファレンスからX-WRITE-API-KEYを作成して控えておく


Next.jsで問い合わせ機能を実装

フォーム機能を実装していきます。

問い合わせ用の関数を作成

Next.jsにはサーバーレス関数を起動できるAPI Routes機能があります。
その機能を利用し、サーバサイド経由でAPIキーを隠蔽してリクエストを送るようにします。

まず、環境変数を利用するために.env.localを作成し、先ほどメモしたX-WRITE-API-KEYを記載します。
NEXT_PUBLIC_を変数の前にを付けるとフロント側にも公開されてしまうので、APIキーなどでは付けない方が良さそうですね。

WRITE_API_KEY="メモしたX-WRITE-API-KEY"


次に以下のような関数とクエリをチェックするタイプガード を用意します。
詳しくはリンクのコード見てもられば!

/pages/api/contact.ts

  // クエリとAPIキーのチェック
  if (!isContact(req.body) || typeof WRITE_API_KEY === "undefined") {
    return res.status(404).end();
  }

  const content = await fetch(`https://xxxxxx.microcms.io/api/v1/contacts/`, {
    headers: { "X-WRITE-API-KEY": WRITE_API_KEY },
    body: JSON.stringify(req.body),
  })
    .then(() => "Created")
    .catch(() => null);

  // CMS側で正しく作成されたかチェック
  if (content !== "Created") {
    return res.status(401).json({ message: "Unauthorized" });
  }

  res.status(200).json({ message: "OK" });

  res.end("Contact enabled");
};


/utils/TypeGuardUtils.ts

const isContact = (item: unknown): item is Contact => {
  const target = item as Contact;

  return (
    "name" in target &&
    typeof target.name === "string" &&
    !!target.name &&
    "email" in target &&
    typeof target.email === "string" &&
    !!target.email &&
    "body" in target &&
    typeof target.body === "string" &&
    !!target.body
  );
};


これで  `/api/contact` でこの関数を起動できるようになりました。
処理としては、以下のチェックをし、問題無ければ200を返すようにしています。問題があればエラーを返します。

  1. クエリとして渡されるオブジェクトが期待通りのオブジェクトか
  2. 実際にmicroCMSのAPIを呼び出して正しく作成されたか


microCMSのAPIの呼び出し処理はラッパーなりを用意した方が無難かもですね。keyの設定なりを毎回しなくてはいけないので。

ページ側の作成

今回はフォームバリデーションライブラリの react-hook-formyup)とUIライブラリのMaterial-UIを利用しています。
上記ライブラリについて詳しくは触れませんが、react-hook-formは公式に記載通り以下の点で優秀だなっと思った最近この頃。

  • 再レンダリングが最小に抑えられている
  • コードの記述量が少ない
  • 外部 UI コンポーネントライブラリとの統合が容易


ページとしては以下の3つを作成します。量が多いので必要なとこだけ説明します。

pages/conatct/index.tsx

  const onSubmit = async (contact: Contact): Promise<void> => {
    try {
      await fetch(baseUrl + "/api/contact", {
        method: "POST",
        headers: {
          "Content-Type": "application/json; charset=utf-8",
        },
        body: JSON.stringify(contact),
      }).then((res) => {
        if (!res.ok) {
          throw Error(`${res.status} ${res.statusText}`);
        }
      });

      void router.push("/contact/success");
    } catch (err) {
      void router.push("/contact/error");
    }
  };


フロント側から上記のように叩くことで先ほど作成した問い合わせ用の関数を起動させています。
これでサーバサイド経由でAPIキーを隠蔽し、リクエストを送るよう出来ました。

「何故フロントからだとAPIキーが隠蔽されないのか」はこのサイトで詳しく解説されておりました。

pages/success/index.tsx
pages/error/index.tsx
上記は、問い合わせの成功時と失敗時の画面です!

これで実装としては完了です。
実装後に作成したフォームで送信してみて、microCMSでその結果が表示出来ていれば完成です!!!


最後に通知が必要な方は、Webpack > API設定でSlackやメール通知などが可能なので設定しておくと良いでしょう。

まとめ

Next.js と microCMS を問い合わせ機能しました。APIキー周りの管理は基本的に自己責任となるので注意が必要ですね。(てかブログ書くの大変)