react-hook-form: form is not re-rendered when using setValue to update a field that was manually registered
Describe the bug
When registering fields manually, the form does not re-render after calling setValue.
To Reproduce
const MyForm = () => {
const { register, unregister, getValues, setValue } = useForm({
defaultValues: { email: '' }
});
useEffect(() => {
register({ name: 'email' });
return () => unregister({ name: 'email' });
}, [register, unregister]);
/* getValues does not work because setValue does not trigger a re-render */
const values = getValues();
const onChange = e => setValue(e.target.name, e.target.value, true);
return <input type="text" name="email" value={values.email} onChange={onChange} />;
};
Expected behavior
Explicitly calling setValue should trigger a re-render
The usual use-case would be to simply pass register into the input’s ref. However, manually registering fields is still required for components that don’t expose a ref prop. The above code snippet is just a contrived example to show that manually registering a field does not work as intended.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 21
- Comments: 43 (33 by maintainers)
actually, that’s not the correct usage…
setValueshouldn’t trigger re-render unless there is an error for the field (react hook form is more towards uncontrolled component). for the controlled component, you should useuseStateandsetValue.setValueshould be used to update the uncontrolled components.For anyone who is registering fields manually like
Autocompletefrom Material UI + React Hook Form you can provide options as a 3rd argument of setValue method.It should work like this
use watch() instead of getValues()
hey @petercpwong just use
watch()! i think it should work!We should be able to use watch on a specific value
const watchfirstName = watch("firstName", props.firstName);with aController.This should trigger a re-render because that’s what’s expected with a watch’like function 😃
This allows to bypass a redundant pattern when
useStateimplemented locally triggers re-rendering of form which then can take into account the change of value for whatever side effect.@balupton, I think that question needs an update because we now have
Controllerfor that.you can set
shouldUnregsiter: falseI believe there is no reason to use a manual register since we already have
Controllerand soonuseControllerthat you can use. If you are working with conditional fields,shouldUnregisteris your friend.can you share a simple codesandbox for what you try to achieve? maybe i am missing the context.
Also, if you could provide a codesandbox that would be helpful.
Let us know your thoughts after you tried both. We can re-open this one if the above solutions doesn’t solve your issue.
You can’t go wrong with either of the two because what you’re doing is just want
Controlleris doing under the hood.thanks @JeromeDeLeon for answering this 😃
@balupton and @petercpwong, have you both tried updating the
react-hook-formand useControllerinstead?Here’s an example of using
Controllerfor UI lib that doesn’t support ref.at the same time, let me think about better* solutions…
There are actually quite a few components that only support controlled props (whether that’s a good design choice is another question).
One notable example: https://polaris.shopify.com/components/forms/text-field
The above component doesn’t expose a
refprop and can only be interfaced withonChangeand setting of thevalueprop.I agree with extra
useStateis bad and I am not supporting that (i was not fully awake in the morning 😃, but whygetValuesduring render.why not just remove value? let the component render the value itself.