🗂
【React Hook Form × Zod】必須エラーが「Required」になる原因と解決策まとめ
React Hook Form(RHF)でZodのカスタムエラーメッセージが反映されず、「Required」が表示されてしまう。。。そんな問題にハマったので、原因と解決策をわかりやすくまとめました。
同じ現象で困っている人の助けになれば幸いです。
結論:defaultValues を設定すれば解決します
defaultValuesを正しく指定することで、RHFがフォーム構造を完全に把握し、Zodのバリデーションエラーが正しくフィールドに紐づくようになります。
なぜdefaultValuesが必要なのか?
背景
以下のようなケースで問題が起きました。
-
defaultValuesを指定していない - ネストしたフィールド(例: items[0].name )を使っている
- MUIの
Controllerを併用している - Zodでは
requiredのカスタムメッセージを定義しているのに、RHFではデフォルトの 「Required」が表示される
RHFはdefaultValuesがないと「フォームにどんなフィールドが存在するのか」を完全に認識できず、内部のformState.errorsが初期化されないケースが発生します。
原因
defaultValuesがない状態では、RHF側がフィールドにエラーがあるか分からない状態になり、zodResolver が返すエラーがフィールドに正しくバインドされません。
その結果、Zodのメッセージではなく、RHFのデフォルトメッセージ「Required」が表示されてしまいます。
解決策:defaultValues を正しく定義する
フォーム開始時に全フィールドの構造を事前定義します。
こうすることで、RHFはフィールドの存在と初期値を正しく把握でき、Zodのバリデーション結果がformState.errorsに正しく反映されるようになります。
const { control, handleSubmit } = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: {
items: [
{ name: "" }
]
}
});
まとめ
Zodでカスタムエラーを設定しても「Required」になる場合は、defaultValuesが不足していることが多いです。
同じ現象で困っている方はぜひ試してみてください。
Discussion