Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue: controlled field validation not updating when disabled is boolean and value is object #12127

Labels
bug Something isn't working

Comments

@quintstoffers
Copy link

Version Number

7.52.0

Codesandbox/Expo snack

https://codesandbox.io/p/sandbox/compassionate-leaf-9gsxtf

Steps to reproduce

Through the reproduction:

  1. Go to https://codesandbox.io/p/sandbox/compassionate-leaf-9gsxtf
  2. Immediately click submit to trigger a validation error
    "invalid" appears below the input
  3. Type something in the input
  4. Form stays invalid, until "submit" is pressed again"

Expected behaviour

Validation is triggered on change and the field is updated to be invalid: false.

Instead, validation is triggered but the field state is not updated. To see this behaviour, click the button to toggle the disabled value to undefined and repeat the steps.

What browsers are you seeing the problem on?

Firefox, Chrome

Relevant log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct
@quintstoffers
Copy link
Author

quintstoffers commented Jul 23, 2024

The issue template didn't give me any space to add some additional info. I did some digging, and it appears this is a consequence of a few different mechanisms at work.

First off, in the change handler:
The value isFieldValueUpdated is false. This is because _updateIsFieldValueUpdated compares the current value with the value that is stored in the form state. It does this using ===, meaning that the check will fail when the two values are not exactly equal.
Logging the values reveals that the two objects are "identical", but not exactly equal.

In useController
The register function is called every render of the component and, because "disabled" is a boolean, _updateDisabledField is called. This sets the value passed to the register function on the form state. useController uses useWatch to get access to the current value.

In useWatch
The function cloneObject is used to clone the value before it is returned.

All together

  1. Change handler is called, updating form state as well as triggering validation
  2. Component re-renders with updated value while asynchronous validation happens
  3. register is called with the cloned value from useWatch, this value is stored in the form state
  4. Validation completes and _updateIsFieldValueUpdated is called
  5. _updateIsFieldValueUpdated compares the new value and the value stored in state. These values are not === equal because the value in the state was cloned by useWatch
  6. trigger and shouldRenderByError are not called because isFieldValueUpdated is false and the component won't update.

@bluebill1049 bluebill1049 added the bug Something isn't working label Aug 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment