Static Formsを使ってNext.jsにお問い合わせフォームを実装する

f:id:kamimura-dev:20200115091914p:plain

こんにちはかみむらです。JAMstackアーキテクチャーや、静的なウェブサイトにお問い合わせフォームを実装するときは、Static Formsで作成できます。


Static Formsとは、発行されたアクセスキーをフォームに含めて、URLにリクエストを送ると、Static Formsの内部で動いてるAmazon SES経由でメールを受け取ることができます。特に静的なウェブサイトに相性がよく、サーバレスなお問い合わせフォームを作成することができます。

今回はNext.jsベースにして、お問い合わせフォームを作成していきます。

Static Formsの公式サイトはこちら
www.staticforms.xyz

プロジェクトの準備

CLIでプロジェクトの雛形を作成します。

$ npx create-next-app my-site

Static Formsの導入手順

Static Formsの導入手順は2つです。導入自体は簡単にできます。

1、アクセスキーの作成
2、メール送信のロジック作成

1、アクセスキーの作成

まずはStatic Formsのウェブサイトにアクセスして、アクセスキーを作成します。自分のメールアドレスを入力して、Create Access Keyをクリックしてください。

f:id:kamimura-dev:20200115085911p:plain

するとStatic Formsからメールが届きます。そこに記載されているアクセスキーをメモしてください。
f:id:kamimura-dev:20200115090226p:plain

このアクセスキーは外部に漏らしてはいけません。なので、dotenvで保護します。

$ yarn add -D dotenv

Next.jsのコンフィグファイルに、アクセスキーを参照できる設定を追加します。

next.config.js

require('dotenv').config();

module.exports = {
  env: {
    access_key: process.env.ACCESS_KEY,
  },
};

そして、.envファイルに取得したアクセスキーを入れます。これで準備は整いました。

.env

ACCESS_KEY=your

2、メール送信のロジック作成

こちらがコードの全体像です。replyToにはあなたのメールアドレスを入れてください。ここではFetch APIを使って、アクセスキーを含めてhttps://api.staticforms.xyz/submitにPOSTリクエストを送っています。
そして、next/routerを使って、メールの送信が成功したら、successページにリダイレクトします。

pages/index.js

import {useState} from 'react';
import Router from 'next/router';

const Home = () => {
  const [contact, setContact] = useState({
    name: '',
    email: '',
    subject: 'お問い合わせ',
    honeypot: '',
    message: '',
    replyTo: '@',
    accessKey: process.env.access_key,
  });

  const [response, setResponse] = useState({
    type: '',
    message: '',
  });

  const handleChange = e =>
    setContact({...contact, [e.target.name]: e.target.value});

  const handleSubmit = async e => {
    e.preventDefault();
    try {
      const res = await fetch('https://api.staticforms.xyz/submit', {
        method: 'POST',
        body: JSON.stringify(contact),
        headers: {'Content-Type': 'application/json'},
      });

      const json = await res.json();

      if (json.success) {
        //成功したらsuccessページに飛ぶ
        Router.push('/success');
      } else {
        setResponse({
          type: 'error',
          message: json.message,
        });
      }
    } catch (e) {
      console.log('An error occurred', e);
      setResponse({
        type: 'error',
        message: 'An error occured while submitting the form',
      });
    }
  };
  return (
    <div>
      <p>{response.message}</p>
      <div>
        <h2>お問い合わせフォーム</h2>
        <form
          action="https://api.staticforms.xyz/submit"
          method="post"
          onSubmit={handleSubmit}>
          <div className="field">
            <label>あなたの名前</label>
            <div>
              <input
                type="text"
                placeholder="お名前"
                name="name"
                onChange={handleChange}
                required
              />
            </div>
          </div>
          <div>
            <label>メールアドレス</label>
            <div>
              <input
                type="email"
                placeholder="メールアドレス"
                name="email"
                onChange={handleChange}
                required
              />
            </div>
          </div>
          <div style={{display: 'none'}}>
            <label className="label">Title</label>
            <div className="control">
              <input
                type="text"
                name="honeypot"
                style={{display: 'none'}}
                onChange={handleChange}
              />
              <input type="hidden" name="subject" onChange={handleChange} />
            </div>
          </div>
          <div>
            <label>メッセージ</label>
            <div>
              <textarea
                placeholder="Your Message"
                name="message"
                onChange={handleChange}
                required
              />
            </div>
          </div>
          <button type="submit">メールアドレスを送信</button>
        </form>
      </div>
    </div>
  );
};

export default Home;

こちらのコードはStatic Formsのサンプルコードを参考にしました。
GitHub - qualascend/staticforms-nextjs-zeit: Integrate static forms with NextJS

こちらはメールの送信が成功したときのページです。

pages/success.js

import React from 'react';

const Success = () => {
  return (
    <div>
      <h2>成功</h2>
    </div>
  );
};

export default Success;

お問い合わせフォームを使ってみる

これでアプリケーションを起動して、メールが送れるか確認してみましょう。localhost:3000にアクセスして下さい。

$ yarn dev

必要事項を入力して、メールアドレスを送信をクリックしてください。

f:id:kamimura-dev:20200115202856p:plain

成功しました。自分のメールボックスをみてください。

f:id:kamimura-dev:20200115203008p:plain

Static Formsからメールが送信されていることが確認できます。

f:id:kamimura-dev:20200115204223p:plain

最後に(重要)

今回はStatic Formsを使って、簡単にお問い合わせフォームを作成しました。やはりここで不安視されるのが、セキュリティーの問題です。Static Formsの公式サイトでは、メールアドレスはAmazon SES経由で送信されるので、使用者の情報は共有しないと書かれています。しかし、Static Formsを採用する場合はFAQ'sに書かれた事項をよく読んで、慎重に検討してください。
www.staticforms.xyz