🗂

【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