如何使用React Hook Form和Yup验证Material UI多选Autocomplete TextField?
你遇到的报错是两个原因共同导致的:
- 多选模式下的Material UI Autocomplete返回值为数组类型,因此用
Yup.string()校验规则类型不匹配,即便选中选项也会触发报错。 - 你直接将
react-hook-form的register绑定到了Autocomplete内部的TextField上,此时RHF收集到的是TextField输入框的搜索值,而不是Autocomplete的选中数组,初始状态下是空字符串,和你预期的数组类型不匹配,因此触发must be a array type的报错。
步骤1:修改Yup校验规则
改用数组类型的校验规则,根据你的选项结构配置校验逻辑,示例如下:
const validationSchema = Yup.object().shape({ daysOfWeek: Yup.array() // 如果你的选项是对象结构,可补充内部字段校验 .of(Yup.object({ label: Yup.string().required(), value: Yup.string().required() })) .min(1, "至少选择一天") .required("Days of the week are required") });
步骤2:使用Controller包裹Autocomplete
register仅适用于原生表单控件,对于MUI Autocomplete这类自定义受控组件,需要使用react-hook-form提供的Controller组件做状态桥接,不需要自己额外维护selected状态,RHF会托管表单状态。
完整修改后代码示例
import { Controller, useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import * as Yup from "yup"; import { Autocomplete, TextField, Typography } from "@mui/material"; const validationSchema = Yup.object().shape({ daysOfWeek: Yup.array() .of(Yup.object({ label: Yup.string().required(), value: Yup.string().required() })) .min(1, "至少选择一天") .required("Days of the week are required") }); function YourFormComponent() { const { formState: {errors}, handleSubmit, control // controller需要用到control实例 } = useForm({ resolver: yupResolver(validationSchema), defaultValues: { daysOfWeek: [] // 初始值设为空数组,避免类型报错 } }); const onSubmit = (data) => { // 此处拿到的data.daysOfWeek就是选中的选项数组 console.log(data.daysOfWeek); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="daysOfWeek" control={control} render={({ field }) => ( <Autocomplete disableClearable disablePortal filterSelectedOptions multiple getOptionDisabled={(option) => !!option.disabled} getOptionLabel={(option) => option.label} id="days-autocomplete" options={daysOfWeekSuggestions} // 直接用controller提供的onChange和value做状态绑定 onChange={(_, value) => field.onChange(value)} value={field.value} renderInput={(params) => ( <TextField required error={!!errors.daysOfWeek} id="daysOfWeek" label="Days of the week" name="daysOfWeek" type="search" {...params} /> )} /> )} /> <Typography color="error" sx={errorSx} variant="inherit"> {errors.daysOfWeek?.message} </Typography> <button type="submit">提交</button> </form> ) }
可选方案:保留自定义selected状态
如果你的业务逻辑需要单独维护选中状态,可以在Controller的onChange回调中同时更新自定义状态:
onChange={(_, value) => { field.onChange(value); setSelected(value); }}
内容的提问来源于stack exchange,提问作者Valerie Hosler
相关产品推荐
相关产品推荐

