👈

RHFで"カスタムフィールド"を作る

2024/07/25に公開

はじめに

React Hook Formカスタムフィールドを作る方法を紹介します。

ここでカスタムフィールドとは、change event等ではないトリガーによって値が変更され、その変更された値がpropsによって返されるようなコンポーネントを使うフィールドです。

環境

react-hook-form@7.52.1

結論

InputEventを模したオブジェクトを作り、field.onChangeに渡して呼び出します。

field.onChange({
  target: {
    value: someValue
  }
})

バリデーションを行わない場合

バリデーションを行わない場合は単にwatchで値を取得し、setValueで値を設定すれば問題ありません。

const form = useForm({
  defaultValues: {
    some: {
      field: {
        name: someDefaultValue
      }
    }
  }
})
<SomeInput
  someValue={form.watch("some.field.name")}
  onSomeValueChange={someValue =>
    form.setValue("some.field.name", someValue)
  }
/>

しかし、setValueをオプションなしで呼び出してもバリデーションが行われないため、formState.isValidが更新されません。

バリデーションを行う場合

値の設定と同時にバリデーションを行うにはControllerを使って結論のように書きます。

const formSchema = z.object({
  some: {
    field: {
      name: someSchema
    }
  }
})
type FormValues = z.infer<typeof formSchema>
const form = useForm<FormValues>({
  resolver: zodResolver(formSchema),
  defaultValues: {
    some: {
      field: {
        name: someDefaultValue
      }
    }
  }
})
<Controller
  control={form.control}
  name="some.field.name"
  render={({ field }) => (
    <SomeInput
      someValue={field.value}
      onSomeValueChange={someValue =>
        field.onChange({
          target: {
            value: someValue
          }
        })
      }
    />
  )}
/>

setValueのオプションでshouldValidatetrueにして呼び出すことでもバリデーションが行われます。

Discussion