Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert values from input radio in boolean in React Hook Form?

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.

Code Sanbox


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 ?&nbsp;
        <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?

like image 616
pom421 Avatar asked Sep 11 '25 06:09

pom421


1 Answers

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.

Code sandbox

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.

like image 83
pom421 Avatar answered Sep 13 '25 21:09

pom421