Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react hook form's getValues() returning undefined

The Question:

  • How do I access the form's values using react-hook-form's Controller without using setValue() for each input?

The Problem: I'm creating my own set of reusable components and am trying to use React Hook Form's Controller to manage state, etc. I'm having trouble accessing an input's value and keep getting undefined. However, it will work if I first use setValue().

CodeSandbox example

 return (
    <form onSubmit={onSubmit}>
      <WrapperInput
        name="controllerInput"
        label="This input uses Controller:"
        type="text"
        rules={{ required: "You must enter something" }}
        defaultValue=""
      />
      <button
        type="button"
        onClick={() => {
          
          // getValues() works if use following setValue()
          const testSetVal = setValue("controllerInput", "Hopper", {
            shouldValidate: true,
            shouldDirty: true
          });

          // testGetVal returns undefined if setValue() is removed
          const testGetVal = getValues("controllerInput");
          console.log(testGetVal);
        }}
      >
        GET VALUES
      </button>

      <button type="submit">Submit</button>
    </form>
  );

More info:

I don't understand why getValues() is returning undefined. When I view the control object in React dev tools I can see the value is saved. I get undefined on form submission too.

My general approach here is to use an atomic Input.tsx component that will handle an input styling. Then I use a WrapperInput.tsx to turn it into a controlled input using react-hook-fom.

like image 863
dumdum3000 Avatar asked Aug 12 '26 09:08

dumdum3000


1 Answers

Lift the control to the parent instead and pass it to the reusable component as prop.

// RegistrationForm.tsx
...
  const {
    setValue,
    getValues,
    handleSubmit,
    formState: { errors },
    control, 
  } = useForm();
...

return (
  ...
      <WrapperInput
        control={control} // pass it here
        name="controllerInput"
        label="This input uses Controller:"
        type="text"
        rules={{ required: "You must enter something" }}
        defaultValue=""
      />
)
// WrapperInput.tsx
const WrapperInput: FC<InputProps> = ({
  name,
  rules,
  label,
  onChange,
  control, /* use control from parent instead  */
  defaultValue,
  ...props
}) => {
  return (
    <div>
      <Controller
        control={control}
        name={name}
        defaultValue={defaultValue}
        render={({ field }) => <Input label={label} {...field} />}
      />
    </div>
  );
};

Codesandbox

like image 196
Badal Saibo Avatar answered Aug 14 '26 12:08

Badal Saibo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!