I have input radio in React Hook Form and I try to use it as real boolean, instead of string.
I know that RHF have valueAsNumber
to convert it as number. I thought that setValueAs
was a generic way to allow any conversion but I can't make it work.
const schema = z.object({
name: z.string().min(4, { message: "4 caractères minimum pour le name" }),
developer: z.boolean() // A real boolean is expected here
});
export default function App() {
const {
register,
handleSubmit,
watch,
formState: { errors }
} = useForm({
resolver: zodResolver(schema),
defaultValues: {
name: "John",
developer: false // default as boolean
}
});
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<input type="text" placeholder="Name" {...register("name")} />
<p>
Is developer ?
<label>
Oui
<input
{...register("developer", {
setValueAs: (val) => true // Try to make it as a real boolean but doesn't work
})}
type="radio"
value={true}
/>
</label>
<label>
Non
<input
{...register("developer", {
setValueAs: (val) => false
})}
type="radio"
value={false}
/>
</label>
</p>
<input type="submit" />
</form>
);
}
Any idea?
I find out how to get a boolean from a radio input in RHF.
The solution with setValueAs, as I tried before, only works for text input (like type="text" or type="number"). For radio button, even if the value is a string, it doesn't work.
So it can be solved by using a Controller component.
function MyBooleanInput({ control, name }) {
return (
<Controller
control={control}
name={name}
render={({ field: { onChange, onBlur, value, ref } }) => (
<>
<label>
Oui
<input
type="radio"
onBlur={onBlur} // notify when input is touched
onChange={() => onChange(true)} // send value to hook form
checked={value === true}
inputRef={ref}
/>
</label>
<label>
Non
<input
type="radio"
onBlur={onBlur} // notify when input is touched
onChange={() => onChange(false)} // send value to hook form
checked={value === false}
inputRef={ref}
/>
</label>
</>
)}
/>
);
}
This way, values are real booleans and zod doesn't throw an error.