How to trigger re-render with `setValue` using react-hook-form?

Viewed 3375

I have a simple form with a select field, it's react-hook-form for validation and everything. There's a Controller which renders a Material UI Select. I would like to set the value of such select using setValue from outside the component (in the root of the form, where all controls reside).
This is the piece of code I'm using (slightly simplified not to waste too much of your time)

type Props = {
  name: string;
  control: Control<any>;
  options: SelectOptions[];
};
const Select: FunctionComponent<Props> = ({
  name,
  control,
  options,
}) => (
  <Controller
    control={control}
    name={name}
    render={({ field: { onChange, value } }) => {
      return (
        <FormControl>
          <MuiSelect onChange={onChange}>
            {options.map((o) => (
              <MuiSelectItem key={o.key} value={o.value}>{o.label}</MuiSelectItem>
            ))}
          </MuiSelect>
        </FormControl>
      )
    }}
  />
);

As far as changing the value of the select, setValue works magically. When I feed a new value, it works as intended. The problem (I guess) is the component is not re-rendered, so the old value is still shown. I'm not sure how to fix this thing and docs did not help a lot. Any help is much appreciated, thanks!

2 Answers

As @knoefel said I tried setting the defaultValue="" but doesn't work for me(maybe because I am using FormProvider). So what I did is use watch instead of value

<Controller
  name='name'
  control={control}
  render={({ field: { onChange } }) => (
    <Select
      dropdownValues={dropdownValues}
      value={watch('name')}
      onChange={onChange}
    />
  )}
/>

I think you just forgot to set the value prop of <Controller /> to your <MuiSelect />. You also have to set a defaultValue for your <Controller /> field, either via the defaultValue prop or via useForm.

<Controller
  control={control}
  name={name}
  defaultValue=""
  render={({ field: { onChange, value } }) => {
    return (
      <FormControl>
        <MuiSelect onChange={onChange} value={value}>
          {options.map((o) => (
            <MuiSelectItem key={o.key} value={o.value}>{o.label}</MuiSelectItem>
          ))}
        </MuiSelect>
      </FormControl>
    )
  }}
/>

Edit BasicSelect Material Demo (forked)

Related