react-hook-form: useController/Controller doesn't support native checkbox input without value

Describe the bug Toggling an input of type checkbox without a proper value managed by useController() or <Controller> is not possible as the value is stuck as "" (or "on" if value attribute is omitted).

To Reproduce Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/s/react-hook-form-controlled-checkboxes-not-working-wwmcs
  2. Click on Submit to verify that the RHF model matches the UI form state ({ withDefaultValue: true })
  3. Click on either checkbox
  4. Submit the form again
  5. Notice how the corresponding value is now "" rather than true or false
  6. Click on the same checkbox again
  7. Notice how the checkbox cannot be unchecked and is stuck

Codesandbox link (Required) https://codesandbox.io/s/react-hook-form-controlled-checkboxes-not-working-wwmcs

Expected behavior Calling the onChange function provided by useController/<Controller> with a ChangeEvent having input.target.type === "checkbox" && input.target.value === "") should toggle the value between true/false rather than setting it to ""

Desktop (please complete the following information):

  • OS: Mac OSX
  • Browser: Chrome
  • Version: 88.0.4324.150

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 20 (14 by maintainers)

Most upvoted comments

Thanks, @mogelbrod for your understanding and support. I wish there are more reasonable developers like yourself, we can really push this library to the next level. I will do some more testing tmr beofre it’s getting merge and published at v7. ❤️

@bluebill1049 Sounds great - I just started migrating to the V7 beta anyway! The other changes look solid as well 💯 I’m really appreciative of all the work you put into this library by the way, and the quick response times on questions and issues is nothing short of amazing ❤️

Feel free to close this issue if the PR gets merged 👍

I think I have a find a solution, probably not going to patch this on V6 (afraid of breaking change with value as boolean instead of string) but get that in V7.

Ok, I just had a quick play it’s actually tricky… because checkbox value="on" by default. On top of that, we can’t determine or predict what the user is after for the form submission as well, some of them could after checked while others want checked to return value.

@mogelbrod if you interested to contribute, feel free to send a PR as well, otherwise I will get to it tonight after work.

Thanks, @mogelbrod for the group checkbox, I think it’s better to maintain your own useState. 👍

I think that looks like a great solution! The only potential issue that I can think of would be arrays of native checkboxes with value set where the user expects the model value to be an array containing the values of the checked inputs. From what I’ve seen it doesn’t look like this code would be responsible for that use case though - if not then I’m all for this change 👍

The diversity here is some users want the value, and some do want the checked for checkbox. I think the above change would resolve this problem for native checked, while the user still can hijack the onChange to get the desired input value.

I was thinking about this last night, this maybe the solution.

import isUndefined from '../utils/isUndefined';
import isObject from '../utils/isObject';
import isPrimitive from '../utils/isPrimitive';

export default (event: any) =>
  isPrimitive(event) ||
  !isObject(event.target) ||
  (isObject(event.target) && !event.type)
    ? event
    : isUndefined(event.target.checked)
    ? event.target.value
    : event.target.checked;