如何将 MUI Select 与 react-hook-form 一起使用?
Posted
技术标签:
【中文标题】如何将 MUI Select 与 react-hook-form 一起使用?【英文标题】:How to use MUI Select with react-hook-form? 【发布时间】:2020-11-23 23:07:38 【问题描述】:我使用 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>
我发现的一件事是,如果我将原生 select
与 ref
一起使用,效果很好。
此外,我尝试将 inputRef
属性更改为 SelectProps
属性,但也没有用。
【问题讨论】:
看看Controller:react-hook-form.com/api#Controller 【参考方案1】:使用带有 React hook 形式的 Material-ui 中的 Select 组件需要您使用 Controller 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
【讨论】:
如何处理 onChange 事件? 在这种情况下,我们没有 onChange bc 输入由 DOM 处理,即不受控制的组件。 是的,正如@YungHK 所说,react-hook-form
使用不受控制的输入。如果您需要表单中输入的值,可以使用 watch:react-hook-form.com/api#watch
为避免以下错误,您需要确保传递一个有效的默认值:Material-UI: A component is changing the uncontrolled value state of Select to be controlled. Elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled Select element for the lifetime of the component.
是的 Paku 可以使用有效的默认值谢谢大家【参考方案2】:
这是我的代码,希望它可以帮助,需要使用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>
这里使用native select,不需要setValue,但value总是字符串
<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>
【讨论】:
【参考方案3】: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>
【讨论】:
你的演示有错误A component is changing an uncontrolled input to be controlled
@Randall 这是来自 MUI 的可怕警告,因为 RHF 默认使用不受控模式,在不受控模式下,value
未定义,defaultValue
是可选的,但在此 MUI 组件中,您需要出于某种原因明确提供一个。无论如何我修正了我的答案,它现在应该可以正常工作了。【参考方案4】:
✔ 我遇到了同样的问题,这就是我解决我的问题的方法:
<Select ... onChange=e => register( name: 'academicLevel', value: e.target.value )/>
more info
【讨论】:
【参考方案5】:这是一个使用带有 React 钩子形式的 Material-UI 的示例。您需要在 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>
【讨论】:
【参考方案6】:当您使用带有材质 UI 的 react-hook-form 时,您不需要使用 onChange 和 setState。仅使用 inputRef 即可!
【讨论】:
问题是关于使用选择【参考方案7】:只需要将寄存器传递给Input Ref
<Select
variant="outlined"
name="reason"
inputRef=register( required: true )
>
【讨论】:
以上是关于如何将 MUI Select 与 react-hook-form 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章