はじめに
Webサイトを作っている時、入力していない場合はバリデーションをかけず、一文字でも入力している場合はemailのバリデーションをかけるという流れで少し詰まったので備忘録として書き残しておきます。
問題
emailの入力フォームで
- 入力は任意(nullでもいい)
- 入力した場合はemailの形式であるかバリデーション
という二つを両立させる方法がわからなかった
解決方法
追記です
X(Twitter)でもっといい方法を教えていただきました!
The solution proposed in the referenced thread has always worked well for me.👌
— moshyfawn (@moshyfawn) January 9, 2024
z.string().email().optional().or(z.literal(''))
ということで、
z.string().email().optional().or(z.literal(''))
のみで今回タイトルにあるバリデーションは問題なく行えるようです!
そもそも正規表現を自前で書いた理由が、zodの.email
では日本語の文字を許容してしまうという情報に基づいたものでしたが、バージョン3.22.0にて修正されていたようです🫨
実際に確認せずに古い情報を信じてコードを書くのはダメですね...
バージョン3.22.0以前であれば以下の対応で問題ないかと思われます。
superRefine
を使用する。
const registerFormValidation = z
.object({
email: z.string().nullable(),
})
.superRefine(({ email }, ctx) => {
if (email !== null && email.length > 0) {
const regex =
/^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/;
if (!regex.test(email)) {
ctx.addIssue({
path: ["email"],
code: "custom",
message: "メールアドレスの形式が不正です",
});
}
}
});
まず、email: z.string().nullable(),
で値がnullの時はバリデーションをとおるようにします。
そのあと、superRefine
をemailの文字数が1以上の時正規表現を用いてテストします。
正規表現に当てはまらなかった場合、ctx.addIssueを登録してエラーメッセージを生成します。
おわりに
もっといい方法があれば教えてください...!
参考サイト