Main featured image

Next.js/TypeScriptのウェブサイトにStatic Formsでサーバレスなお問い合わせフォームを作成する

Next.js
TypeScript
StaticForms

Next.js/TypeScript のウェブサイトに Static Forms でサーバレスなお問い合わせフォームを作成する方法です。

Static Forms はメール送信をサーバレスで実行してくれるサービスです。

フォームの情報は Static Forms 側で保持せず、内部的には Amazon SES を利用してメール転送を行っているとのことです。

また、Qualascend 社がスポンサーについており無料で提供出来るとのことです。

個人情報の取り扱いは Privacy Policy を読んで自己判断でご利用お願いします。

それでは問い合わせフォームを作成していきましょう。

環境
  • macOS Catalina 10.15.5(19F101)
  • VSCode 1.52.1
  • Next 10.0.5
  • React 16.14.0
  • TypeScript 4.0.5
  • Node 14.9.0
  • yarn 1.22.4
Next.js プロジェクトの雛形を作成する

今回は筆者が作成したテンプレートを利用します。

yarn create next-app --example "https://github.com/kazuma-fujita/next-ts-lint-mui-template" next-static-forms-sample

こちらのテンプレートは Next.js/TypeScript/ESLint/Prettier の利用環境があらかじめ用意されています。

Static Forms AccessKey 環境変数を用意する

プロジェクトルートに .env.local ファイルを作成し以下を入力します。

  • .env.local
STATIC_FORMS_ACCESS_KEY=

こちらは Static Forms の AccessKey の環境変数で、秘匿情報なので外部に漏れないようにします。

.env.localcreate next-app した時にあらかじめ .gitignore されています。

また .env.localyarn dev の development build 時に読み込まれます。

後ほど解説しますが、本番環境はホスティング先で環境変数を設定します。

環境変数をクライアントサイドで利用できるようにする

次にプロジェクトルートに next.config.js ファイルを作成します。

.env.* で設定した環境変数はサーバサイドの Node.js 環境でのみ取得できます。

具体的には src/pages 配下で動作するサーバサイド処理の getStaticProps function 内や src/pages/api 配下のコードで利用できます。

それ以外のコードでも環境変数を使えるようにする為、 next.config.js で env 設定をします。

設定内容は以下です。

  • next.config.js
module.exports = {
  env: {
    STATIC_FORMS_ACCESS_KEY: process.env.STATIC_FORMS_ACCESS_KEY,
  },
};

.env.* の値は process.env.{.envで設定した環境変数キー名} で取得できます。

next.config.js のサーバサイド処理で取得した .env.* の値をクライアントサイドに渡しています。

これでどこでも process.env.* で環境変数が利用できるようになりました。

問い合わせフォームの状態管理をする関数を実装する

問い合わせフォームの画面実装から、状態管理のロジックを分離させる為のカスタム hooks 関数を実装します。

以下の 3 ファイルを作成します。

  • src/interfaces/ContactParams.ts
export interface ContactParams {
  name: string;
  email: string;
  message: string;
}

form の値を保持する為のオブジェクトです。

  • src/state/contact/useFormState.ts
export const useFormState = <S>(
  initialState: S
): [S, (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void] => {
  const [contact, setContact] = useState<S>(initialState);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    setContact({ ...contact, [event.target.name]: event.target.value });
  };

  return [contact, handleChange];
};

form の入力値を管理する為のカスタム hooks です。

  • src/state/contact/useSendContactForm.ts
const SUBJECT_TITLE = 'お問い合わせ';
const STATIC_FORMS_URL = 'https://api.staticforms.xyz/submit';
const ACCESS_KEY = process.env.STATIC_FORMS_ACCESS_KEY as string;

export const useSendContactForm = (): [string, (postData: ContactParams) => void] => {
  const router = useRouter();
  const [errorMessage, setErrorMessage] = useState('');
  const sendContactForm = useCallback(async (postData: ContactParams) => {
    const postParams = {
      ...postData,
      subject: SUBJECT_TITLE,
      replyTo: '@', // 送信メールのデフォルト返信先を問い合わせ元のメールアドレスにする
      accessKey: ACCESS_KEY,
    };
    const response = await fetch(STATIC_FORMS_URL, {
      method: 'POST',
      body: JSON.stringify(postParams),
      headers: { 'Content-Type': 'application/json' },
    })
      .then((response) => response.json())
      .then((jsonData) => jsonData as { success: boolean; message: string })
      .catch((e) => {
        console.error('An error occurred', e);
        const error = e as Error;
        return { success: false, message: error.message };
      });
    response.success ? void router.push('contact_success') : setErrorMessage(response.message);
  }, []);
  return [errorMessage, sendContactForm];
};

form の値を Static Forms へ post するカスタム hooks です。

Static Forms は { success: boolean; message: string } のレスポンスを返します。

Static Forms からのレスポンスの値 response.success が true の場合、問い合わせ完了画面である contact_success へ遷移します。

Static Forms からのレスポンスがエラーの場合、response.message の値を setErrorMessage にセットし form 画面にエラーを表示します。

問い合わせフォームを実装する

以下の 2 ファイルを作成します。

  • src/pages/index.tsx
const IndexPage: React.FC = () => {
  const [contact, handleChange] = useFormState<ContactParams>({
    name: '',
    email: '',
    message: '',
  });
  const [errorMessage, sendContactForm] = useSendContactForm();
  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    sendContactForm(contact);
  };

  return (
    <div>
      <h2>お問い合わせ</h2>
      {errorMessage && <p>{errorMessage}</p>}
      <form 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>
          <label>お問い合わせ内容</label>
          <div>
            <textarea placeholder='Your Message' name='message' onChange={handleChange} required />
          </div>
        </div>
        <button type='submit'>お問い合わせをする</button>
      </form>
    </div>
  );
};

export default IndexPage;

問い合わせフォームの画面実装です。

先程作成した useFormState hooks でフォームの値を管理しています。

useSendContactForm hooks の sendContactForm 関数で入力値を Static Forms に送信しています。

errorMessage で Static Forms のエラー時にエラー文言を画面表示しています。

  • src/pages/contact_success.tsx
const ContactSuccessPage: React.FC = () => (
  <div>
    <h2>お問い合わせありがとうございます</h2>
  </div>
);

export default ContactSuccessPage;

シンプルなお問い合わせ完了画面です。

以上で一通りの問い合わせフォーム実装は完了です。

次に Static Forms の AccessKey を設定します。

Static Forms の AccessKey を取得・設定する
post image

まず Static Forms にアクセスして Step 1 - Create Access Key にお問い合わせメールを受信するメールアドレスを入力してください。

post image

入力したメールアドレス宛に AccessKey が送信されるので控えてください。

先程作成した .env.local に AccessKey を追記してください。

STATIC_FORMS_ACCESS_KEY={AccessKeyを追記}
ホスティング先の環境変数を設定する

後はホスティング先で環境変数を設定します。

今回は Vercel の設定方法を説明します。

Vercel のコンソールで対象のプロジェクトを開きます。

Settings から Environment Variables 画面を開きます。

post image

Add New の Which type of Environment Variable do you want to add?Plaintext を選択します。

What's its name and value? の NAME には STATIC_FORMS_ACCESS_KEY VALUE に AccessKey を入力します。

In which Environments would you like to make it available? には設定する環境を選択します。

環境を複数選択して、共通の環境変数を設定することも可能です。

Save ボタンを押して設定完了です。

問い合わせメール送信を確認する

全ての準備が完了したので、お問い合わせフォームに値を入力して送信してください。

post image

設定したメールアドレス宛にお問い合わせメールが受信されていることを確認してください。

終わりに

メール送信部分を自分で用意するとなると、AWS を利用する場合は Amazon API Gateway/AWS Lambda/Amazon SES などの組み合わせで実装することが多いと思います。

今回、Static Forms を利用してお手軽にお問合せフォームが作成できました。

実装のサンプルコードは Github にあるので参照ください。

Written by ZUMA a.k.a. Kazuma. Web/Mobile App developer.  My profile.
Tags
Archives
2021-072021-062021-052021-042021-032021-022021-01
Recent Posts