reactjsnext.jsreact-hook-formchakra-ui

react-hook-form question: why getValues does not return most current value?


I have radio buttons: A, B, and C.

Under button B, there's a select box and I want to make this select box 'required' only when B is selected.

Here's simplified code:

interface ButtonFormType {
    notificationType: "A" | "B" | "C";
    selectedId?: string;
}
const {
        register,
        handleSubmit,
        getValues,
        watch,
        formState: { errors },
    } = useForm<ButtonFormType>();

.
.
.

return(
 <form onSubmit={submit}>
  <RadioGroup defaultValue={getValues("buttonType")}>
    <VStack>
      <Radio {...register("buttonType")} value={"A"}> Button A </Radio>
      <Radio {...register("buttonType")} value={"B"}> Button B </Radio>
      <FormControl isInvalid={!!errors[`selectedId`]}>
         <Select
            placeholder={"select"}
            {...register("selectedId", {
                required:
                   getValues("buttonType") === "B"
                   ? "please select id"
                   : false,
            })}
         >
            {idList.map(({ id, title }) => {
               return (
                  <option key={id} value={id}>
                       {title}
                  </option>
                                        );
            })}
         </Select>
      </FormControl>
     <Radio {...register("buttonType")} value={"C"}> Button C </Radio>
    </VStack>
   </RadioGroup>
                  
   <HStack marginY="40px" spacing={4}>
      <Button type="submit"> Submit </Button>
   </HStack>
</form>
)

when I choose button B (not select anything from select box) and hit the submit button, it does not give me any error.

If I hit the submit button again, it gives error message.

I inspected and found out that getValues("buttonType") is not updated as soon as I change buttonType.

It's updated once I hit the submit button. why?

I could solve this issue by changing getValues to watch like this

required:
                   watch("buttonType") === "B"
                   ? "please select id"
                   : false,

but still can't understand why getValues does not work. Does anybody know?


Solution

  • You can refer to this description.

    The difference between watch and getValues is that getValues will not trigger re-renders or subscribe to input changes.

    So getValues doesn't know your real time change, but watch does.