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

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}}).

For external controlled component

If you are using V3, i would recommend to use react-hook-form-input https://github.com/react-hook-form/react-hook-form-input

import React from 'react';
import useForm from 'react-hook-form';
import { RHFInput } from 'react-hook-form-input';
import Select from 'react-select';

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
];

function App() {
  const { handleSubmit, register, setValue, reset } = useForm();

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      <RHFInput
        as={<Select options={options} />}
        rules={{ required: true }}
        name="reactSelect"
        register={register}
        setValue={setValue}
      />
      <button type="button">Reset Form</button>
      <button>submit</button>
    </form>
  );
}

If you are using V4, i would recommend to use Controller https://react-hook-form.com/api/#Controller

import React from 'react';
import Select from 'react-select';
import { TextField } from "@material-ui/core";
import { useForm, Controller } from 'react-hook-form';

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' },
];

function App() {
  const { handleSubmit, control } = useForm();

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      <Controller
        as={<Select options={options} />}
        control={control}
        rules={{ required: true }}
        onChange={([selected]) => {
          // React Select return object instead of value for selection
          return { value: selected };
        }}
        name="reactSelect"
      />

      <Controller
        as={<TextField />}
        name="firstName"
        control={control}
      />

      <button>submit</button>
    </form>
  );
}

The idea to wrap your controlled component and collecting data within while still isolate re-render inside the external controlled component.