Gatsby
ハイドレーション前から静的な HTML で動き、その後は fetch で拡張される Gatsby のフォームと、シークレットキーで送信する Gatsby Function。
Gatsby はビルド時にすべてのページを HTML に描画します。フォームに本物の action を付ければ、React がハイドレーションする前や、バンドルの読み込みに失敗した場合でも送信できます。ハイドレーション後は、コンポーネントが fetch で送信し、結果をその場に表示します。
ブラウザーから送信する
フォーム ID を追加する
.env.production GATSBY_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxxGatsby がブラウザーのコードに公開するのは
GATSBY_で始まる変数だけで、ビルド時に埋め込まれます。gatsby develop用に、同じ行を.env.developmentにも追加してください。コンポーネントを追加する
src/components/contact-form.js import * as React from "react"; const endpoint = `https://ikiform.com/f/${process.env.GATSBY_IKIFORM_FORM_ID}`; export default function ContactForm() { const [status, setStatus] = React.useState("idle"); const [message, setMessage] = React.useState(""); async function onSubmit(event) { event.preventDefault(); setStatus("sending"); try { const response = await fetch(endpoint, { method: "POST", headers: { Accept: "application/json" }, body: new FormData(event.currentTarget), }); const result = await response.json(); if (result.ok) return setStatus("sent"); setMessage(result.error.message); } catch { setMessage("Couldn't reach the server. Try again."); } setStatus("error"); } if (status === "sent") return <p>Thanks, we got it.</p>; return ( <form action={endpoint} method="post" onSubmit={onSubmit}> <label> Email <input name="email" type="email" autoComplete="email" required /> </label> <label> Message <textarea name="message" rows={5} /> </label> <input type="hidden" name="_redirect" value="https://example.com/thanks/" /> <input name="_gotcha" type="text" tabIndex={-1} autoComplete="off" hidden /> {status === "error" ? <p role="alert">{message}</p> : null} <button disabled={status === "sending"}>Send</button> </form> ); }src/pages/contact.jsなど任意のページから描画し、JavaScript なしの場合のリダイレクト用にsrc/pages/thanks.jsを追加します。フィールドエラーや SDK の人間確認を使うには、React のガイドのように拡張してください。
Gatsby Function から送信する
Gatsby Function はシークレットキーを付けて送信を転送できるので、許可ドメインと人間確認をスキップできます。動くのは、Gatsby のアダプターを使った Netlify など、Gatsby Functions に対応したホストだけです。GitHub Pages のような完全な静的ホストでは動きません。IKIFORM_FORM_ID と、submissions:write スコープを持つシークレットキーを IKIFORM_SECRET_KEY として保存します。ブラウザーに届かないよう、GATSBY_ は付けないでください。
export default async function handler(req, res) {
if (req.method !== "POST") return res.status(405).end();
const response = await fetch(`https://ikiform.com/f/${process.env.IKIFORM_FORM_ID}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${process.env.IKIFORM_SECRET_KEY}`,
},
body: JSON.stringify(req.body),
});
res.status(response.status).json(await response.json());
}Gatsby は JSON とフォームエンコードのボディを req.body に解析するので、ページからはどちらの形式でも /api/contact に送信できます。その場合、すべての送信がレート制限上は Function の IP アドレスを共有します。サーバーから送信するを参照してください。
許可ドメイン
これはブラウザーからの送信に当てはまります。Gatsby Function からの送信はシークレットキーを使うので、チェックをスキップします。
| フォームが動く場所 | 許可ドメインに追加するもの |
|---|---|
gatsby develop と gatsby serve | localhost。http://localhost:8000 と http://localhost:9000 に一致します。Ikiform が比較するのはホスト名だけで、ポートは比較しません。 |
| 自分のドメイン | example.com(www.example.com も含まれます) |
| Netlify | your-site.netlify.app。デプロイプレビュー(deploy-preview-12--your-site.netlify.app)やブランチデプロイ(branch--your-site.netlify.app)はそのサブドメインではないので、テストする間はプレビューの正確なホストを追加してください。 |
| Cloudflare Pages | your-project.pages.dev。abc123.your-project.pages.dev のようなプレビュー URL はそのサブドメインなので、すでに一致します。 |
netlify.appやpages.devだけを追加しないでください。他の人のサイトも含め、そのホスト上のすべてのサイトが一致してしまいます。
テストのチェックリスト
gatsby buildを実行し、public/contact/index.htmlを開きます。フォームのactionがundefinedではなく、フォーム ID で終わっているはずです。- 許可ドメインに
localhostを入れてgatsby serveを実行し、送信します。お礼のメッセージがフォームに置き換わるはずです。 - JavaScript をオフにし、再読み込みして送信します。ローカルでは Ikiform のサンクスページが、
https:のドメインでは/thanks/が表示されるはずです。 - Function を使う場合は、デプロイプレビューで
/api/contactに送信し、送信データが Ikiform に表示されることを確認します。
トラブルシューティング
| 症状 | 原因 | 対処 |
|---|---|---|
404 not_found になり、action が /f/undefined で終わっている | 変数に GATSBY_ が付いていない、またはビルド時に設定されていなかった | GATSBY_IKIFORM_FORM_ID という名前にして、再ビルドします。 |
Function が 403 forbidden を返す | シークレットキーが別のワークスペースのもの、無効化されている、または submissions:write がない | そのスコープを持つシークレットキーを作成します。 |
デプロイ後に /api/contact が 404 を返す | ホスティング先が静的ファイルしか配信しない | Gatsby Functions に対応したホストにデプロイするか、ブラウザー版を使います。 |
送信データが origin_mismatch でスパムフィルターの下に届く | 送信したページが、フォームの許可ドメインに含まれていない | 上の表のホストを追加します。Reject を選んでいる場合、同じ送信には代わりに 403 origin_not_allowed が返ります。 |