react-hook-form: the watch method and values from useFieldArray are out of sync

Describe the bug The watch method does not recognize the updates from useFieldArray. In the codesandbox i am console logging all watched values out. Any changes from the form field values should be reflected in that watch method, including the modified values in useFieldArray but in this case the values are not accurate.

To Reproduce Steps to reproduce the behavior:

  1. Go to the codesandbox
  2. open console
  3. Click append
  4. Then click delete twice
  5. See error Object {test: Array[3]} (it should be a length of 2)
  6. Click append again.
  7. See that the array index is one behind now.
  8. Delete all items and see there is still an array of 3.

Codesandbox link (Required) https://codesandbox.io/s/issue-usefieldarray-watch-broken-kph9x

Expected behavior When fields are modified from useFieldArray, the watch method should reflect the same modified array. This way we are able to get the subscribe to the values externally for our needs.

Desktop (please complete the following information):

  • OS: Mac
  • Browser: chrome

Additional context

The reason we need this to work is for using the watch method combined with useEffect to dispatch changes to a context provider so the user can see a live update of their form. In our case, we don’t want to manually setup onChange events for every field but watch/subscribe to all fields and update our context so we can display the live information elsewhere.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 44 (26 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @bluebill1049!

Just wanted to chime in and make our use-case completely clear so you’re not throwing darts in a dark room.

Our team is coming to the end of building a platform which has Campaigns which map to various web pages. We have a live-preview builder where the user can change settings for their Campaign and watch the affects live. To do this we are watching for values to change in the form and then are passing the values up to a Context which is used by the previewer. As such, it’s important to us that we’re able to know when values change and dispatch the new values.

We’re keeping track of our dependencies on the project and are budgeting that, post release, we’ll be able to financially support our dependencies on a regular basis, as well as contribute ourselves. So we’re hoping to partner with RHF long-term and have a great on-going relationship where we show our support and appreciation with our open-source partners.

If there’s any more context we can provide to help clear up our use-case, please feel free to ask any questions.

here you go: 5.3.2-beta.1

Much appreciated! useFieldArray is our last roadblock to refactor fully into RHF from Final Form. Everything else is working great! 🙌

@bluebill1049 This issue still persists in v5.3.1

I’m not sure what happened because you had the issue fixed in your patch.

Here is the codesandbox: https://codesandbox.io/s/issue-usefieldarray-watch-broken-v531-bwovf

  1. add append
  2. notice nothing gets added to the array
  3. click delete
  4. notice justWatchedValue is undefined & allWatchedValue is not right either
  5. append again and we’re one value behind.

Thanks a lot for the detailed issue report as well.

let’s track it there: https://github.com/react-hook-form/react-hook-form/issues/1404 cause it’s more specific.

RE: dirtyFields

Okay I don’t want to get too off track with this because it’s not the main issue and I know you’re working hard on fixes, but I would like you to think about the relationship between formState.dirty and formState.dirtyFields with me.

If formState.dirty becomes true shouldn’t formState.dirtyFields show you what is dirty?

This relationship can be summed up by asking two questions (codesandbox below):

console.log("[is form state dirty?]", formState.dirty);
console.log("[if yes what fields are dirty?]", [...formState.dirtyFields]);

You see, when I click a button in field array the formState.dirty becomes true. Except dirtyFields never tells me what specifically is dirty.

https://codesandbox.io/s/issue-dirtyfields-v532-beta1-6w2y8?file=/src/App.js

That’s a valid point for dirtyFields. 🤔I think you are right here, will fix this behaviour.

RE: dirtyFields

Okay I don’t want to get too off track with this because it’s not the main issue and I know you’re working hard on fixes, but I would like you to think about the relationship between formState.dirty and formState.dirtyFields with me.

If formState.dirty becomes true shouldn’t formState.dirtyFields show you what is dirty?

This relationship can be summed up by asking two questions (codesandbox below):

console.log("[is form state dirty?]", formState.dirty);
console.log("[if yes what fields are dirty?]", [...formState.dirtyFields]);

You see, when I click a button in field array the formState.dirty becomes true. Except dirtyFields never tells me what specifically is dirty.

https://codesandbox.io/s/issue-dirtyfields-v532-beta1-6w2y8?file=/src/App.js

Thanks for the fast response @bluebill1049 you rock!

Re: Issue 2. I was thinking formState touched & dirtyFields would change if you interact with the field array - maybe that’s not the case?

Let’s take a look 1, 2 tmr.

Much appreciated!

thanks for understanding @JasonTheAdams 🙏

Hahah! The dark side of automation. 😆

I’d be fine with a beta since it’s specifically for this issue (which we greatly appreciate). We can then immediately report back on this and hopefully bump up to the next stable release next week.

strangle… I will take a look at it.

Awesome! Thank you!

yea @JasonTheAdams, i agree with your statement above. The reason behind such behaviour is so when user invoke watch the first time will not return undefined since none of the inputs have been registered.

Let me do some investigation, see if we can improve this behaviour, worse case i will add a description in the doc and provide alternative solution with formState.

@bluebill1049 Amazing turn around time! Did you happen to notice, though, that if you remove all of the instances it snaps back to the initial values instead of an empty array?