Zodのファイルスキーマを作成
import { z } from "zod";
// PDFファイルの検証スキーマ
const schema = z.object({
/** 名前 */
nickname: z.string().min(1, { message: "名前を入力してください" }),
/** 年齢 */
age: z
.number({ message: "年齢を半角数字で入力してください" })
.int({ message: "年齢を整数で入力してください" })
.gte(12, { message: "年齢を12歳以上で入力してください" }),
/** メールアドレス */
email: z.union([
z
.string()
.email({ message: "メールアドレスの形式で入力してください" })
.nullish(),
z.literal(""),
]),
/** JSONデータ */
jsonData: z
.string()
.min(1, { message: "JSONデータを入力してください" })
.refine((val) => {
try {
JSON.parse(val);
return true;
} catch {
return false;
}
}, { message: "正しいJSON形式で入力してください" }),
/** PDFファイル */
pdfFile: z
.any()
.refine((file) => file instanceof File && file.type === "application/pdf", {
message: "PDFファイルを選択してください",
}),
});
React Hook Formとの統合
import { FC } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
// スキーマから型を生成
type Inputs = z.infer<typeof schema>;
export const SchemaFormSample: FC = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Inputs>({
mode: "onTouched",
resolver: zodResolver(schema),
});
const onSubmit = (data: Inputs) => {
// フォームの送信処理
console.log("Validated data:", data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>
名前
<input type="text" {...register("nickname")} />
</label>
{errors.nickname && <p>{errors.nickname.message}</p>}
</div>
<div>
<label>
年齢
<input
type="number"
{...register("age", { valueAsNumber: true })}
/>
</label>
{errors.age && <p>{errors.age.message}</p>}
</div>
<div>
<label>
メールアドレス
<input type="email" {...register("email")} />
</label>
{errors.email && <p>{errors.email.message}</p>}
</div>
<div>
<label>
JSONデータ
<input type="text" {...register("jsonData")} />
</label>
{errors.jsonData && <p>{errors.jsonData.message}</p>}
</div>
<div>
<label>
PDFファイル
<input type="file" {...register("pdfFile")} />
</label>
{errors.pdfFile && <p>{errors.pdfFile.message}</p>}
</div>
<div>
<button type="submit">submit</button>
</div>
</form>
);
};