GatsbyプロジェクトでNetlify Formsを試してみた

2021-06-20

概要

ちょっと NetlifyForms を試してみました。詳細な説明は公式ドキュメントを参照。

Netlify をおまじない付き(data-netlify=”true”)で利用すると、デプロイ時にHTMLを解析して、フォームを処理してくれるのでAPI呼び出しや余分な JavaScript を組み込む必要がないそうです。今回は、Gatsby から使えるか試してみました。

雛形プロジェクトの作成

Gatsby のスターターを使います。

$ gatsby new netlify-forms https://github.com/gatsbyjs/gatsby-starter-default
$ cd netlify-forms
$ code .

VSCode が起動されているので、ターミナルで更に以下を実行します。

$ npm install
$ npm audit fix

Prettierの設定

これは趣味の問題ですが、.prettierrc を適当に設定します。

{
  "arrowParens": "always",
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
}

コンタクトフォームの作成(CSSなしの暫定)

src\components\ContactForm.js を作成します。

import React, { useState } from 'react';

function ContactForm() {
  const [formState, setFormState] = useState({
    name: '',
    email: '',
    message: '',
  });

  const encode = (data) => {
    return Object.keys(data)
      .map(
        (key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])
      )
      .join('&');
  };

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

  const handleSubmit = (e) => {
    fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: encode({ 'form-name': 'contact', ...formState }),
    })
      .then(() => alert('メールを送信しました。'))
      .catch((error) => alert(error));

    e.preventDefault();
  };

  return (
    <form
      onSubmit={handleSubmit}
      name="contact"
      method="post"
      data-netlify="true"
      data-netlify-honeypot="bot-field"
    >
      <input type="hidden" name="form-name" value="contact" />
      <label htmlFor="name">名前</label>
      <input
        id="name"
        type="text"
        name="name"
        onChange={handleChange}
        value={formState.name}
        placeholder="名前を入力してください。"
      />
      <label htmlFor="email">メールアドレス</label>
      <input
        id="email"
        type="email"
        name="email"
        onChange={handleChange}
        value={formState.email}
        placeholder="メールアドレスを入力してください。"
      />
      <label htmlFor="message">メッセージ</label>
      <textarea
        id="message"
        name="message"
        value={formState.message}
        onChange={handleChange}
        placeholder="メッセージを入力してください。"
      />
      <button type="submit">送信</button>
    </form>
  );
}

export default ContactForm;

コンタクトフォームを src\pages\index.js から利用するため2行追加します。

import React from 'react';
import { Link } from 'gatsby';
import { StaticImage } from 'gatsby-plugin-image';

import Layout from '../components/layout';
import Seo from '../components/seo';
import ContactForm from '../components/ContactForm'; // ★この行を追加

const IndexPage = () => {
  return (
    <Layout>
      <Seo title="Home" />
      <h1>Hi people</h1>
      <p>Welcome to your new Gatsby site.</p>
      <p>Now go build something great.</p>
      <StaticImage
        src="../images/gatsby-astronaut.png"
        width={300}
        quality={95}
        formats={['AUTO', 'WEBP', 'AVIF']}
        alt="A Gatsby astronaut"
        style={{ marginBottom: `1.45rem` }}
      />

      <ContactForm />    // ★この行を追加

      <p>
        <Link to="/page-2/">Go to page 2</Link> <br />
        <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
      </p>
    </Layout>
  );
};

デプロイ

次の手順でデプロイします(詳細は省略)。

  1. GitHub にリポジトリを作りコードを push
  2. Netlify から GitHub リポジトリを指定してデプロイ(サイト名は適当に変更)

デプロイしたサイトは次のようになります。

暫定デプロイ結果

スタイリングの追加

import React, { useState } from 'react';
import * as styles from './ContactForm.module.css'; // ★この1行を追加
  • 最終的には次のようになりました。
CSSの追加

Netlifyダッシュボードの Forms

  • 以下から受信したメッセージ等を確認できます。
  • 現在、Forms Level 0 となっていますが、課金してこれをLevel 1にすると一ヶ月1000通まで受け取れるようになったりします。
NetlifyダッシュボードのForms
  • 上図で contact をクリックすると次の感じで送信されてきた情報を見ることができます。また、CSVファイルとしてダウンロードも可能です。
送信されてきたメッセージの確認

まとめ

  • Netlify Forms を使うと、ちょっとしたおまじないを書くだけで、あとは Netlify のビルド時にうまいことやってくれるので、フロントエンドだけのコードを書くだけで、コンタクトフォームが実現できます。
  • 今回はGatsbyを用いた静的サイトジェネレーションだったのですが、単純にHTMLCSSで作るサイトであれば、更におまじないのコード量は少なくなります。
  • 実際の本格的なコンタクトフォームの場合は、もっと送信前のチェックのコード(フォームバリデーション)が必要になると思います。