react-hook-form: watch vs. useWatch array length inconsistency when using useFieldArray

Describe the bug Not sure if this is a bug/can be improved but… when using useFieldArray to insert/remove item to the fields, the resulting output (array) of that useWatch doesn’t have a consistent length with the array length of updated fields after the insertion/removal.

To Reproduce Steps to reproduce the behavior:

  1. Go to the CSB link, clear the console after render.
  2. Click on “insert” or “remove”.
  3. See the console. Check the length of the fields vs. the length of the useWatchedItems on the first render loop.

Codesandbox link (Required) https://codesandbox.io/s/watch-vs-usewatch-field-array-length-inconsistency-bi8it?file=/src/App.jsx:1365-1650

Expected behavior The length of the fields and the length of the useWatchedItems should be the same on each render cycle.

Additional context When watch is used instead of useWatch though, the watched array length seems to be consistent with the fields array length on each render. 👍

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Ah ok, thanks. So you’re saying this is expected, right? 😃

Yes, the last re-render will bring the updated field values.

Previously its a bug because it didn’t return the correct wath value, i will do some investigation with inconsistent watch value. I know the root cause, because useWatch need to trigger another setState to update the value, but worth to do some investigation, if not working then will close this issue.

Ohh, didn’t expect that you’d go the extra mile for this. Was actually already quite satisfied with some workaround, like:

const items = useWatch({
    name: 'items',
    defaultValue: fieldArrayItems,
    control,
  });

cons itemsLength = fieldArrayItems.length;
// ...some much more logic that depends on `itemsLength`

But it’s a great feeling to expect that I’m gonna be able to do this:

const items = useWatch({
    name: 'items',
    defaultValue: fieldArrayItems,
    control,
  });

cons itemsLength = items.length;
// ...some much more logic that depends on `itemsLength`

Your effort is most appreciated, Bill – as always – thank you soo muucch! 😃

I wouldn’t say it can’t be improved, but i did try last night and it’s not working out…

because watch gets called even before the child component. order below:

  1. fields (re-render)
  2. watch
  3. useWatch