AstroでPreactとZodを使ってお問い合わせフォームのバリデーションを作成する方法
先日、Astroを使ったサイトでPreactとZodを用いてお問い合わせフォームのバリデーションを実装する機会があったので、作成手順を紹介します。Zodとはスキーマ定義やバリデーションのためのJavaScriptライブラリです。Preactは、Reactと同じような機能を提供しながら、Reactに比べてファイルサイズが小さく、パフォーマンスが高いことが特徴のJavaScriptのフロントエンドライブラリです。
1. 必要なライブラリのインストール
このフォームを作成するにあたり、preactとzodという2つのライブラリが必要になります。以下のコマンドを使用してインストールしてください。
npm install preact zod
2. フォームの作成
まず、フォームのコンポーネントを作成します。フォームの要素を定義し、必要な値をstateで管理します。
contact-form.jsx
import { useState } from "preact/hooks";
import { z } from "zod";
export const ContactForm = () => {
// バリデーションスキーマの定義
const validationSchema = z.object({
name: z.string().min(1, { message: "お名前をご入力ください" }),
email: z
.string()
.min(1, { message: "メールアドレスをご入力ください" })
.email({ message: "正しいメールアドレスをご入力ください" }),
message: z
.string()
.min(1, { message: "お問い合わせの詳細をご入力ください" }),
});
// フォームの値を管理するstate
const [formValues, setFormValues] = useState({
name: null,
email: null,
message: null,
});
// フォームのバリデーション結果を取得
const formValidateResult = validationSchema.safeParse(formValues);
// フォームのバリデーションが成功しているかどうかを取得
const isAllValid = formValidateResult.success;
// バリデーションエラーがある場合はエラーメッセージを取得
const errors = isAllValid ? undefined : formValidateResult.error.format();
// フォームの送信処理
const submitForm = (event) => {
if (!isAllValid) {
event.preventDefault();
return;
}
// フォーム送信先のURLを指定
const formUrl = "送信先URL";
const form = document.getElementById("form");
form.action = formUrl;
};
// フォームを描画
return (
<div>
<div>
<div>
<form method="post" id="form" onSubmit={submitForm}>
<div>
<div>
<div>
<span>お名前</span>
<span>
必須
</span>
</div>
<div>
<span>
<input
type="text"
name="お名前"
placeholder="お名前をご入力ください"
onInput={(e) =>
setFormValues({ ...formValues, name: e.target.value })
}
/>
{formValues.name !== null && errors.name && (
<span>
{errors.name._errors[0]}
</span>
)}
</span>
</div>
</div>
<div>
<div>
<span>メールアドレス</span>
<span>
必須
</span>
</div>
<div>
<span>
<input
type="text"
name="メールアドレス"
placeholder="メールアドレスをご入力ください"
onInput={(e) =>
setFormValues({ ...formValues, email: e.target.value })
}
/>
{formValues.email !== null && errors.email && (
<span>
{errors.email._errors[0]}
</span>
)}
</span>
</div>
</div>
<div>
<div>
<span>お問い合わせ詳細</span>
<span>
必須
</span>
<div>
<span>
<textarea
name="お問い合わせ詳細"
placeholder="お問い合わせの詳細をご入力ください"
onInput={(e) =>
setFormValues({
...formValues,
message: e.target.value,
})
}
></textarea>
{formValues.message !== null && errors.message && (
<span>
{errors.message._errors[0]}
</span>
)}
</span>
</div>
</div>
</div>
<div>
<div>
<button
disabled={!isAllValid ? true : false}
type="submit"
name="送信する"
value=""
>
送信する
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
);
};
以下の箇所は、フォームの入力欄に入力された文字列を収集し、その値をformValues
オブジェクトのname
プロパティに保存するための処理を行っています。具体的には、以下のことを行っています。
<input>
要素にonInput
というイベントリスナーを設定して、入力欄に文字が入力されるたびに、onInput
イベントが発生します。- このイベントが発生するたびに、
setFormValues()
関数が呼び出され、formValues
オブジェクトのname
プロパティの値が、入力欄に入力された文字列に更新されます。
onInput={(e) =>
setFormValues({ ...formValues, name: e.target.value })
}
onBlur={(e) =>
setFormValues({ ...formValues, name: e.target.value })
}
そして、以下の箇所で更新された値をもとに、エラーがある場合、かつ初期表示ではない場合にエラーメッセージが表示されます。
{formValues.name !== null && errors.name && (
<span>
{errors.name._errors[0]}
</span>
)}
以下は必須項目のバリデーションが全て成功していない場合にdisabled属性をtrueにしてフォームを送信できないようにしています。
<button
disabled={!isAllValid ? true : false}
type="submit"
name="送信する"
value=""
>
送信する
</button>
参考: Zod | Error Handling in Zod