Netlify Formを利用すれば、serverlessのGatsbyにも問い合わせフォームを簡単に作れるでしょう。しかし、無料プランは1カ月100通のメッセージしか受信できないので、スパム対策しっかりしたほうがいいでしょう。( ´艸`)
普通のhttp postであれば、Netlify Formページのマニュアルを参照すれば難しくない組み込めますが、今回はAjaxで実装してみましょう。
要望
ランディングページにNetlify Formで組み込んだ問い合わせフォームのスパム対策します。
スパム対策。
-
Honeypot field
-
reCAPTCHA 2
Honeypot field
Honeypot fieldは英語なんですが、ここへ。
Ajaxでフォームをコミットするため、formにnetlify-honeypot
を追加する必要がありません。非表示にinputを組み込めば簡単にできます。
const [inputs, setInputs] = React.useState({});
const handleChange = React.useCallback(
(event) => {
setInputs({
...inputs,
[event.target.name]: event.target.value,
});
},
[inputs],
);
<form>
<p hidden> <label htmlFor="bot-field"> Don’t fill this out: <input name="bot-field" onChange={handleChange} /> </label> </p> <label>Email:<input type="text" name="email" onChange={handleChange} /></label>
</form>
reCAPTCHA v2
reCAPTCHAのキーペアを取得
https://www.google.com/recaptcha/admin, reCAPTCHA v2のサイトキーとシークレットキーを取得。
サイトキー
とシークレットキー
をコピーします。
Netlifyに環境変数を追加
Settings
→ Build & deploy
→ Environment
に下記を追加します。
- SITE_RECAPTCHA_KEY: サイトキー
- SITE_RECAPTCHA_SECRET: シークレットキー
ソースコードの修正
-
react-google-recaptcha
のインストールyarn add react-google-recaptcha
-
formに
data-netlify
とdata-netlify-recaptcha
を追加<form data-netlify="true" data-netlify-recaptcha="true" > ... </form>
-
サイトキーを
.env.development
に書き込むと、developモードで起動したら、Gatsbyが自動的にprocess.envに読み込んでくれます。(製品版のビルドするとき、同じ内容を.env.production
に書き込まなければいけない)SITE_RECAPTCHA_KEY=6LdtK6YZAAAAAK3iDB-14qX7bJv2d1KuIz_GR7LT
-
reCAPTCHAコンポーネントをformに追加
import ReCAPTCHA from 'react-google-recaptcha'; const [recaptchaValue, setRecaptchaValue] = React.useState(""); const handleChangeReCAPTCHA = React.useCallback((value) => { setRecaptchaValue(value); }, []); <form data-netlify="true" data-netlify-recaptcha="true" > ... <ReCAPTCHA sitekey={process.env.SITE_RECAPTCHA_KEY} onChange={handleChangeReCAPTCHA} /> </form>
-
submitするとき、パラメータ名
g-recaptcha-response
としてvalueをPOSTするfetch("/", { ..., body: { "g-recaptcha-response": encodeURIComponent(recaptchaValue), } })
-
ソースコードを整理
import ReCAPTCHA from 'react-google-recaptcha'; function ContactForm() { const [inputs, setInputs] = React.useState({}); const [recaptchaValue, setRecaptchaValue] = React.useState(""); const handleChange = React.useCallback( (event) => { setInputs({ ...inputs, [event.target.name]: event.target.value, }); }, [inputs], ); const handleChangeReCAPTCHA = React.useCallback((value) => { setRecaptchaValue(value); }, []); const handleSubmit = React.useCallback( (event) => { const submitForm = event.currentTarget; event.preventDefault(); event.stopPropagation(); if (recaptchaValue != null && recaptchaValue !== "") { fetch("/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: encodeObj({ "form-name": "form1", "g-recaptcha-response": recaptchaValue, ...inputs, }), }) .catch(() => console.log('POST ERROR')); } }, [inputs, recaptchaValue], ); return ( <form data-netlify="true" data-netlify-recaptcha="true" onSubmit={handleSubmit} > {/* You still need to add the hidden input with the form name to your JSX form */} <input type="hidden" name="form-name" value="form1" /> <p hidden> <label htmlFor="bot-field"> Don’t fill this out: <input name="bot-field" onChange={handleChange} /> </label> </p> <p> <label>Email: <input type="text" name="email" /></label> </p> <p> <label>Message: <textarea name="message"></textarea></label> </p> <p> <button type="submit">Send</button> </p> </form> ); }
完了
AjaxでNetlify FormをPOSTした場合、意外にワナが多くて、ご参考までに。