Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-hook-form's setValue method is not working if input is in material ui dialog

I tried to use react-hook-form to validate inputs. But I found that if the input is placed in Material UI's dialog component, react-hook-form's setValue is not working as expected, but it works when I remove Dialog component. I guess the reason is that the value is set before the component mounts, but still can't find out the solution.

The value will be retrieved from the server, so I can't use react-hook-form's defaultValues.

https://codesandbox.io/s/react-hook-form-material-ui-twbbw

I have tried to use useState to control the input value, but there is another problem. When clear the input, click submit button, and error message shows, the first letter I key in will not be displayed.

https://codesandbox.io/s/react-hook-form-material-ui-ve2en

like image 808
Sam Avatar asked Dec 30 '19 06:12

Sam


2 Answers

In my case, I was using setValue in a modal. It wasn't working as expected. I had to add shouldUnregister: false in useForm.

const { errors, register, setValue, handleSubmit } = useForm({
resolver: useYupValidationResolver(CustomDomainSchema),
mode: 'all',
shouldUnregister: false,
});

I solved this after reading this Discussion on react-hook-form. Here is a working example on sandbox.

like image 186
Sanan Ali Avatar answered Sep 20 '22 15:09

Sanan Ali


The problem is with the register function. You are registering the Textfield with register after the ref of the Textfield is called.

The useEffect is called to set the name to 123 with setValue after the initial render. If open is true, the dialog content is rendered after the useEffect. After the content is rendered, the ref with register is called and the default value of Textfield (here undefined) is set to be the value of name.

That is why the value of the Textfield is "" on show. You need to call setValue after the render and ref callback is called, so that the value persists.

You have two options to do that:

  1. Set the value async in the useEffect with an async delay (setTimeout or promise) after open changed. So if you add open to the useEffect dependecy array and set the value async, it works. Here is a Sandbox.
  2. Set the default value of either the Textfield or add the default value to the hook with useForm({defaultValues: {name: '123}}).
like image 27
Domino987 Avatar answered Sep 19 '22 15:09

Domino987