react-hook-form: getValues() and watch() don't work correctly with array fields

Describe the bug getValues() and watch() return incorrect values when working with array fields.

To Reproduce

import React from "react";
import ReactDOM from "react-dom";
import useForm from "react-hook-form";

function App() {
  const { register, getValues, watch } = useForm({
    defaultValues: { test: [0, 1] }
  });
  const test = watch("test");

  return (
    <form>
      <h3>getValues: {JSON.stringify(getValues())}</h3>
      <h3>watch: {test}</h3>
      {/* <h3>watch(): {JSON.stringify(watch())}</h3> */}

      <input name="test[0]" ref={register} type="checkbox" />
      <input name="test[1]" ref={register} type="checkbox" />
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/embed/react-hook-form-basic-qgkkp Expected behavior

  • getValues() should have returned {test: [0,1]} (instead got {} on first render and {"test[0]":"on","test[1]":false} after clicking on the first checkbox)
  • watch('test') should have returned [0,1], instead got: undefined.

Desktop (please complete the following information):

  • OS: Win10
  • Browser: Chrome
  • Version: 75

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 5
  • Comments: 26 (16 by maintainers)

Commits related to this issue

Most upvoted comments

Todos:

  • defaultValues inject default value into watch
  • improve watch with array and objects
  • getValues with arugment to flat, default flat to true (similar functionality will apply to watch)
  • defaultValues support array and objects
  • update website with getValues update
  • update website with defaultValues and defaultValue association with watch

Hi you guys! Nice thread and thanks for the solution! I ran into the same scenario as @zernie and have nested getValues() worked like a charm. Can you just please add that to the documentation? image

Agree, It makes sense for defaultValues to be able to get value in watch() first render, but when I am having the following

then it’s not going to work as expected, because it’s not rendered just yet, so I was trying to be consistent there.

I think defaultValue should just override defaultValues. But maybe library should output a warning in this case so it won’t come out as a surprise? Smth like: if (defaultValues[field] && ref.current.defaultValue !== "") console.warn("You're overriding a default value for the field..."), maybe?

what about some type of argument to shape the result from getValues({ flatten: false }), any good suggestion?

Love it! This way we could get the benefits of both approaches. Just gonna need the same argument for watch.