如何将 MUI Select 与 react-hook-form 一起使用?

How to use MUI Select with react-hook-form?

我使用 MUI 和 React Hook Form 在 React 中构建了一个表单。我正在尝试创建一个自定义 TextField 元素作为 Select Input。我希望它是一个不受控制的组件,带有 Ref 道具。我尝试按照 MUI 和 React Hook Form 文档的建议传递 inputRef 道具,但没有成功。

            <TextField
              id="id"
              name="name"
              select
              native="true"
              className={classes.textField}
              label="label"
              margin="normal"
              variant="outlined"
              inputRef={register({ required: "Choose one option" })}
              error={!!errors.name}
            >
              <MenuItem value="">Choose one option</MenuItem>
              <MenuItem value="3">03</MenuItem>
              <MenuItem value="6">06</MenuItem>
              <MenuItem value="9">09</MenuItem>
              <MenuItem value="12">12</MenuItem>
              <MenuItem value="16">16</MenuItem>
              <MenuItem value="18">18</MenuItem>
            </TextField>

我发现的一件事是,如果我使用原生 selectref ,效果很好

此外,我尝试将 inputRef 属性更改为 SelectProps,但没有成功'我也不工作。

将 Material-ui 中的 Select 组件与反应钩子形式一起使用需要您使用控制器实现自定义逻辑 https://react-hook-form.com/api#Controller

这是一个可重复使用的组件,有望简化代码以在您的应用中使用该 Select 组件:

import FormControl from "@material-ui/core/FormControl";
import InputLabel from "@material-ui/core/InputLabel";
import Select from "@material-ui/core/Select";
import { Controller } from "react-hook-form";

const ReactHookFormSelect = ({
  name,
  label,
  control,
  defaultValue,
  children,
  ...props
}) => {
  const labelId = `${name}-label`;
  return (
    <FormControl {...props}>
      <InputLabel id={labelId}>{label}</InputLabel>
      <Controller
        as={
          <Select labelId={labelId} label={label}>
            {children}
          </Select>
        }
        name={name}
        control={control}
        defaultValue={defaultValue}
      />
    </FormControl>
  );
};
export default ReactHookFormSelect;

您可以像这样在您的应用中使用它:

           <ReactHookFormSelect
              id="numero_prestacao"
              name="numero_prestacao"
              className={classes.textField}
              label="Em quantas parcelas?"
              control={control}
              defaultValue={numero_prestacao || ""}
              variant="outlined"
              margin="normal"
            >
              <MenuItem value="">Escolha uma opção</MenuItem>
              <MenuItem value="3">03 parcelas</MenuItem>
              <MenuItem value="6">06 parcelas</MenuItem>
              <MenuItem value="9">09 parcelas</MenuItem>
              <MenuItem value="12">12 parcelas</MenuItem>
              <MenuItem value="16">16 parcelas</MenuItem>
              <MenuItem value="18">18 parcelas</MenuItem>
            </ReactHookFormSelect>

这是使用此组件更新的 codeSandBox,用于信息表单中的选择:

https://codesandbox.io/s/unit-multi-step-form-kgic4?file=/src/Register/Information.jsx:4406-5238

这是我的有效代码,希望对您有所帮助,需要使用 setValue

  <TextField
    fullWidth
    inputRef={register({
      name: 'name',
    })}
    select
    onChange={e => setValue('name', e.target.value, true)}
    label={label}
    defaultValue={defaultValue}
  >
    {options.map((option) => (
      <MenuItem key={option.label} value={option.value}>
        {option.label}
      </MenuItem>
    ))}
  </TextField>

这里使用原生select,不需要setValue,但value总是string

<TextField
    fullWidth
    select
    SelectProps={{
      native: true,
      inputProps: { ref: register, name: 'name' }
    }}
    label={label}
    defaultValue={defaultValue}
  >
    {options.map((option) => (
      <option key={option.label} value={option.value}>
        {option.label}
      </option>
    ))}
  </TextField>

✔ 我遇到了同样的问题,这就是我解决问题的方法:

<Select ... onChange={e => register({ name: 'academicLevel', value: e.target.value })}/>

more info

这是一个使用 Material-UI 和 React 挂钩形式的示例。您需要在 TextField 的 'inputRef' 属性中添加验证。您还需要添加 'onChange' 函数来保持状态更新。 'shouldValidate' 将触发验证。

  <TextField
    select
    name='city'
    inputRef={register({ required: true })}
    onChange={e => setValue('city', e.target.value, { shouldValidate: true })}
    label="City"
    defaultValue="">
    {cityList.map((option, index) => (
      <MenuItem key={index} value={option}>
        {option}
      </MenuItem>
    ))}
  </TextField>

  {errors.city && <ErrorText>City is required</ErrorText>}

当您将 react-hook-form 与 material UI 一起使用时,您不需要使用 onChange 和 setState。仅使用 inputRef 一切正常!

只需要将寄存器传递给Input Ref

 <Select
   variant="outlined"
   name="reason"
   inputRef={register({ required: true })}
  >

RHF v7 更新

下面是 RHF 形式的 MUI Select 的最小代码示例:

const { formState, getValues, watch, register, handleSubmit } = useForm();
const { errors } = formState;
<TextField
  select
  fullWidth
  label="Select"
  defaultValue=''
  inputProps={register('currency', {
    required: 'Please enter currency',
  })}
  error={errors.currency}
  helperText={errors.currency?.message}
>
  {currencies.map((option) => (
    <MenuItem key={option.value} value={option.value}>
      {option.label}
    </MenuItem>
  ))}
</TextField>