👈
RHFで"カスタムフィールド"を作る
はじめに
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
のオプションでshouldValidate
をtrue
にして呼び出すことでもバリデーションが行われます。
Discussion