react-hook-form: Unable to setValue on hidden type inputs

Hi,

Describe the bug I use react-hook-form 3.23.0. I am not to be able to use setValue on type=“hidden” input fields, while setValue works OK on default input fields.

To Reproduce I have this simple component using semantic-ui-react.

import React from "react";
import useForm from "react-hook-form";
import {Form,Button,Radio} from "semantic-ui-react";

const MyForm: React.FC = props => {
  const { register, handleSubmit, setValue } = useForm();

  const onSubmit = (formData) => console.log(formData);

  let data = {
    start: true
  };

  return (
    <>
      <Form onSubmit={handleSubmit(onSubmit)}>
         <Form.Field>
          <label>Start?</label>
          <input
            type="hidden"
            name="start"
            defaultValue={data.start.toString()}
            ref={register({required: true})}
          />

          <Radio toggle name="start_toggle" defaultChecked={data.start}
                    onChange={(e, radio) => {
                        setValue("start", radio.checked)
                      }
                    } />
        </Form.Field>
        <Button primary type="submit">
          Submit
        </Button>
      </Form>
    </>
  );
};

export default MyForm;

Expected behavior I want to use Semantic UI’s Radio component visualized as a toggle. I would like to store the value of the toggle in a backing field (name=“start”). When I have a type=“hidden” as the backing field the value always remains “true” (clicking submit logs the form value and start is always “true” there). However if I remove type=“hidden” and have a default text field then everything works fine and the value of “start” matches the state of the toggle.

Is there anything special in the handling of hidden inputs? Or what am I doing wrong?

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (11 by maintainers)

Most upvoted comments

I am facing the same issue. Hidden fields don’t seem to work correctly… I did manage to get it working by setting CSS display: none instead of using type="hidden"

https://react-hook-form.com/api#watch

you can watch any registered inputs, if you have defined defaultValues in useForm, then it will just flow through.

eg:

const { regsiter } = useForm({ defaultValue: { test: 'bill' } });

const result = watch('test');

<input name="test" ref={regsiter} />

@bluebill1049

you can’t update input hidden value: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/hidden

I’m not sure this is correct. I interpret MDN’s docs as “the user cannot see or edit hidden inputs” – not that you can’t programmatically change hidden inputs to then submit to the server. For our Rails API, we often use dynamically updated hidden inputs to send flags like _destroy to mark an object for destruction.

I’m currently running into this issue myself with some dynamic, deeply nested forms who’s schema is generated by rails and rendered by RHF. When I want to delete an association, I need to set that _destroy flag to true and send it back to the server. Something like this:

const { register } = useForm({ resolver: yupResolver(myDynamicSchema) })
const objectsFromServer = {
  nested_resources: [
    { id: 1, value: 123 }, { id: 2, value: 456 }
  ]
}

const deleteLastObject = () => {
  setValue('nested_resources[1][_destroy]', true)
}

return <div>
  {objectsFromServer.nested_resources.map((obj, idx) => (
    <div>
      {/* unregister and hide visible input for deleted object */}
      {obj._destroy ? (
        <i>Object deleted</i>
      ) : (
        <input
          ref={register}
          name={`nested_resources[${idx}][value]`}
          defaultValue={obj.value} />
      )}

      {/* hidden input must be present to send to server */}
      <input
        type="hidden"
        ref={register}
        name={`nested_resources[${idx}][_destroy]`}
        defaultValue={obj._destroy} />
    </div>
  ))}

  <button onClick={deleteLastObject}>Delete</button>
</div>

I know useFieldArray is meant for this kind of behavior, but I couldn’t quite get it to work. I can build a full demo of the issue soon, but I just wanted to mention a use-case for updating registered hidden inputs. At the moment, my issue is that when I mark an object for destruction, its other (required) fields appear to still be registered, and it fails validation. Even though only the hidden _destroy field is present.

I think we can set hidden input value: https://codesandbox.io/s/misty-sea-41ko0?file=/src/App.js

you can’t update input hidden value: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/hidden

try with display: none;

Hey @bluebill1049 I’ve encountered a similar issue with a child input used for file upload which is hidden, touched does not record the change unless I remove the hidden from input element. Any other gotchas?

Does not work: <input type=“file” name=‘files’ hidden accept=‘image/*’ ref={register({ required: true })} defaultValue={watch(“files”, FileChanged)} />

This works: <input type=“file” name=‘files’ accept=‘image/*’ ref={register({ required: true })} defaultValue={watch(“files”, FileChanged)} />

going to close this issue for now 😃 feel free to reopen if you have other questions

looks like is the defaultValue which causing this issue:

https://codesandbox.io/s/infallible-frost-kclhg