Material UI 表单重置时切换输入未更新

Material UI switch inputs not updating on form reset

我正在使用 react-hook-form 来构建我的表单,这是一个很棒的工具。但是,我似乎无法根据 redux 的 return 值让 <Switch /> 元素滑动(false/true)。 当我点击表单上的“重置”时,我所有的输入都会重置。我的 Switch 控件没有重置,它们仍然停留在它们的最后一个值上,不管它是否可能被重置。关于如何解决这个问题有什么想法吗?

我的开关

<FormControlLabel
  control={
    <Switch
      size="medium"
      name="familyFriendly"
      defaultChecked={formState.content.isFamilySafe}
      {...register('content.isFamilySafe')}
    />
  }
  label="Family Friendly"
/>

重置按钮

   <button
        type="button"
        onClick={() => {
          reset(formState, {
            keepErrors: true,
            keepDirty: true,
            keepIsSubmitted: false,
            keepTouched: false,
            keepIsValid: false,
            keepSubmitCount: false,
          });
        }}
      >
        reset
      </button>

useForm挂钩

  const formState = useSelector(selectDynamicForm);
  const {
    register,
    control,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<IFormInput>({});

我认为 react-hook-form 需要知道它“关注”的是复选框而不是文本输入。由于 <Switch /> 是一个包装组件,ref 现在以 div 元素而不是 input 元素为目标。但是,有一个 inputRef 道具 material-ui 转发到输入元素。

const { ref, ...rest } = register('content.isFamilySafe');

<FormControlLabel
  control={
    <Switch
      size="medium"
      name="familyFriendly"
      defaultChecked={formState.content.isFamilySafe}
      inputRef={ref}
      {...rest}
    />
  }
  label="Family Friendly"
/>

或者您可以围绕 <Switch /> 个组件的注册函数创建一个包装器:

function registerSwitch(name) {
  const { ref: inputRef, ...rest } = register(name);
  return { inputRef, ...rest };
}

<FormControlLabel
  control={
    <Switch
      size="medium"
      name="familyFriendly"
      defaultChecked={formState.content.isFamilySafe}
      {...registerSwitch('content.isFamilySafe')}
    />
  }
  label="Family Friendly"
/>

第三种解决方案是使用辅助函数重写道具:

const fixSwitchProps = ({ ref: inputRef, ...rest }) => ({ inputRef, ...rest });

<FormControlLabel
  control={
    <Switch
      size="medium"
      name="familyFriendly"
      defaultChecked={formState.content.isFamilySafe}
      {...fixSwitchProps(registerSwitch('content.isFamilySafe'))}
    />
  }
  label="Family Friendly"
/>

MUI 的 <Switch /> 组件使用 checked 而不是 value 的实际值界面略有不同。 RHF 的 register returns 一个 value 属性 你散布在 <Switch /> 组件上,所以 checked 永远不会在 RHF 和 [=11 之间链接=] 组件.

所以你应该使用RHF的<Controller />组件来控制这个外控组件。查看 here 了解更多信息。

<FormControlLabel
    control={
      <Controller
        control={control}
        name="content.isFamilySafe"
        render={({ field: { value, ...field } }) => (
          <Switch {...field} checked={!!value} size="medium" />
        )}
      />
    }
    label="Family Friendly"
/>

您还需要通过 useForm 为您的输入设置 defaultValue,因为这是 reset 正常工作所必需的。来自 docs:

If your form will invoke reset with default values, you will need to call useForm with defaultValues instead of setting the defaultValue on individual fields.