はじめに
Webサイトを作成する際にフォームが必要になること多いですよね。フロントエンドは比較的簡単に実装できますが、フォームのためだけにバックエンドを実装するのは面倒です。Google Formは便利ですが、そのままの見た目はちょっとデザイン的にアレですよね...
今回はReact Form Hook と Google Formを連携させてお手軽にフォームを作成する方法をご紹介します。ついでにValidationのためにZodも使用します。 ValidationはReact Form Hook単体でもできますが、Zodを使用することで、JSXがすっきりとした見た目になります。 加えて、TypeScriptを使用する際の型を提供してくれます。
前提
Google Formを作成した経験がある
React Form Hookを使用した経験がある
Zodを使いますが、前提知識は不要です
まずはGoogle Formを作成
Reactプロジェクトを作成
筆者は普段、viteでReactを作成しています。
npm create vite@latest
TypeScriptは使用しないのでReact > JavaScriptのテンプレート
を選択してください
App.css
とindex.css
の内容を全て削除します。
index.cssに下記cssを追加してください
* {
box-sizing: border-box;
}
p {
padding: 0;
margin: 0;
margin-top: 10px;
}
button {
margin-top: 10px;
}
必要なpackageをinstallします
npm install react-hook-form
Zodを使用するので下記2つもインストールしてください
npm install @hookform/resolvers
npm install zod
App.jsxにコードを追加する
今回使用する全てのコードです。
FormURLのurl
とFormFieldNames
の内容は、後程各自が作成したGoogle Formから取得します
import "./App.css";
import { useForm } from "react-hook-form";
// Zod
import { zodResolver } from "@hookform/resolvers/zod";
import * as zod from "zod";
// Zodのschema定義 (validation)
const schema = zod.object({
name: zod.string().min(1, { message: "必須項目です" }),
age: zod.preprocess(
(v) => Number(v),
zod.number().min(2, { message: "年齢は2桁以上である必要があります" })
),
});
// Google FormのActon
const FormURL =
"https://docs.google.com/forms/u/0/d/e/1FAIpQLSe6jUbmv6snQNZV-dm8zyqB-9-z7AIGZ2Y5wBAjTJCKW3hScw/formResponse";
// Google Formから取得したname属性の値
const FormFieldNames = {
name: "entry.587594010",
age: "entry.414111699",
};
function App() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
// zodを使用する設定
resolver: zodResolver(schema),
});
const onSubmit = async (data) => {
try {
await fetch(FormURL, {
method: "POST",
// urlEncodeされた値をbodyに入れる
body: provideUrlEncodedFormData(data),
// 通常ではcorsに弾かれる (返却値のstatusは常に0 後述...)
mode: "no-cors",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
// 成功後の処理を記述する (画面遷移とか)
} catch (e) {
alert("送信に失敗しました。ネットワーク状況を確認してください");
}
};
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="fom-item">
<label>
<p>名前</p>
<input type="text" {...register("name")} />
</label>
<p className="error-message">{errors.name?.message}</p>
</div>
<div className="form-item">
<label>
<p>年齢</p>
<input type="text" {...register("age")} />
</label>
<p className="error-message">{errors.age?.message}</p>
</div>
<button type="submit">
送信
</button>
</form>
</>
);
}
// request bodyに必要なurlEncodeされた値を提供
// originalのform情報を{entry.{number}: value}に変換する
function provideUrlEncodedFormData(originalFormData) {
const result = {};
Object.keys(originalFormData).map(
(key) => (result[FormFieldNames[key]] = originalFormData[key])
);
return new URLSearchParams(result).toString();
}
export default App;
Google Formから必要な情報を取得する
App.jsxのうちFormURLのurl(action)
とFormFieldNamesのentry
をGoogle Formから取得します。
Google Formの右上の目玉マーク(プレビュー)を押します
画面サイズが小さいと隠れてしまうので気をつけてください
表示されたプレビュー画面で検証ツールを開き<form
で検索するとactionを見つけることができます
inputのentryはプレビューに仮データを入力することで簡単に見つけることが可能です
entryの写し間違いを防ぐためにも、全てのinputで仮データを入れて取得するのが無難です
必要な情報を取得したらGoogle Form右下のフォームをクリアを押してください
FormFieldNamesのkeyはregisterで定義したものにあわせてください
const FormFieldNames = {
name: "entry.587594010",
age: "entry.414111699",
};
<form onSubmit={handleSubmit(onSubmit)}>
// ...省略
<input type="text" {...register("name")} />
// ...省略
<input type="text" {...register("age")} />
// ...省略
</form>
動作確認
Google Formの連携はこれで完了です。
動作確認の前にGoogle Formに閲覧制限がかかっていないか確認します。
Google FormプレビューのURLをクリップボードにコピーし、ブラウザのシークレットモードで閲覧可能か確認してください。
閲覧できない場合は、閲覧制限がかけられているので、リンクを知っている人全員がGoogle Formを閲覧できるよう変更してください。
npm run dev
でサーバーを起動してください。
どちらもvalidationが機能しています。
名前と年齢を記入し送信ボタンを押します。
Google Formの回答を確認すると、データが登録されています
ここまででReact Form Hookを利用したGoogle Form連携は完了です。
注意点
実装にあたっては下記の注意点を考慮した上で作成してください
fetch後に返されるstatusは常に0 (下記2点の場合ユーザー側は送信に失敗していることに気づけない)
1 google側のサーバーの問題 (滅多にない)
2 誤ってGoogle Formを削除した場合や必須項目をGoogle Formにのみ追加した場合
(管理側が間違えなければ問題ない)
Wi-Fi(ネットワーク)非接続状態の検知はtry{}catch(){},async,awaitの使用で検知可能
カフェのFree Wi-Fiで1時間経過後通信が遮断されたタイミングで送信ボタンが押された場合など...
text以外の取り扱い
今回はtextのみ扱いましたが、checkboxやradioも同様に作成することが可能です。
下記記事はHTML, CSS, JavaScriptでGoogle Formと連携する方法です。
記事の中ではcheckbox, radio, select等も扱っています。参考にしてください。
終わりに
React Form HookもZodも触ったことがない状態で、土日休暇を利用して実装してみました。
Google Form連携を行わない場合でもReact Form Hookは有用なので、実装した甲斐がありました。
この記事が誰かのお役に立つと嬉しいです。
参考