dohomi/react-hook-form-mui

What should I do if I want to access the value of a specific field through useWatch?

Closed this issue ยท 4 comments

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Summary ๐Ÿ’ก

First, It seems like a minor issue, but I'm sorry for asking this question.

I ended up using react-hook-form-mui in a hurry for this project. I want to access and use the value of a specific field through useWatch, but I don't know how to do it. The documentation is very poor. I don't know if I should import useWatch from react-hook-form or react-hook-form-mui, and I don't know how to use it.

I tried it as below, but when the value changes, not only that component but all components on the page are re-rendered. Is this normal behavior if I use useWatch? Or is there another correct way and am I missing it? What am I missing?

Examples ๐ŸŒˆ

import type { Dayjs } from 'dayjs';
import { useForm, useWatch } from 'react-hook-form';
import { DateTimePickerElement, FormContainer } from 'react-hook-form-mui';

type FieldValues = {
  start: Dayjs | null;
  end: Dayjs | null;
};

export default function DateTimeForm() {
  const { control } = useForm<FieldValues>({ defaultValues: { start: null, end: null } });
  const start: Dayjs | null = useWatch({ control, name: 'start' });

  return (
    <FormContainer reValidateMode="onChange" mode="onChange">
      <DateTimePickerElement label="Start" name="start" control={control} required disablePast />
      <DateTimePickerElement label="End" name="end" minTime={start && start.add(1, 'hour')} required disablePast disableIgnoringDatePartForTimeValidation />
    </FormContainer>
  );
}

I feel this once again, but the documentation seems very poor... ๐Ÿฅฒ
It would be nice if you updated the example to be more detailed, at least for the main features. Since the usage is not completely the same as react-hook-form, you cannot blindly trust the official documentation of react-hook-form.

useWatch is only available in components inside the FormContainer, i.e. you must write a subcomponent in which you can import it from RHFM.

I find this subcomponent pattern bad and do the following:

const context = useForm({
  defaultValues,
  resolver,
})

const foo = context.watch('foo')

<FormContainer formContext={context} onSuccess={onSubmit}>
  //...
</FormContainer>

Please note you need to pass the defaultValues and resolver to useForm not the element for it to work. It might lead to more re-renders than necessary but like I said, I don't want to write a subcomponent for parts of my form if not necessary...

@akullpp you can pass control object provided by useForm to useWatch.

const { control } = useForm({
  defaultValues,
  resolver,
})
const foo = useWatch({ name: "foo", control })

Thanks a lot. now I kind of understand how it works.
If you just use useForm and useWatch without creating a child component, the advantage of react-hook-form in minimizing re-rendering seems to disappear. I can't decide which is the better choice, but anyway, thank you for your time and help.

@stoicjone you have more granular re-render if you use a child component and watch only in that child component a specific value.
Beside that you can also don't use the and pass control to all form components if performance is an issue