React-Hook-Form+Yup Resolver3.1.1:允许null初始值但提交需对象
React-Hook-Form + React-Select + Yup Resolver 3.1.1 校验失效问题
在TS NextJS13项目中,使用React-Hook-Form的Controller结合React-Select组件,搭配Yup Resolver做表单校验时遇到以下问题:
- React Hook Form不允许
Controller的默认值为undefined,因此将默认值设为null - 升级到Yup Resolver 3.1.1后,要求以Schema作为表单类型推导依据,必须给Select对应的Yup Schema添加
.nullable()才能兼容null默认值 - 但添加
.nullable()后,表单允许在未选择有效{value:string, label:string}类型对象的情况下提交,破坏了必填校验逻辑
3.1.0版本可用代码示例
import * as yup from 'yup'; import { useForm, Controller } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import Select from 'react-select'; // 定义选项类型 interface SelectOptionType { label: string; value: string; } // 定义表单类型 interface InputType { category: SelectOptionType | null; } // Yup校验规则 const schema = yup.object().shape({ category: yup .object() .shape({ label: yup.string().required("Tag is required"), value: yup.string().required("Tag is required"), }) .required() }); // 初始化表单 const { control, handleSubmit } = useForm<InputType>({ resolver: yupResolver(schema), defaultValues: { category: null, } });
3.1.1版本的问题
3.1.1版本要求移除手动定义的InputType,由Yup Schema自动推导表单类型。但直接给Schema添加.nullable()后,校验逻辑失效,允许category为null时提交表单。同时当前Yup版本不再支持.nullable(true)的写法。
解决方案
通过.nullable().required()的组合,既兼容null默认值,又确保提交时必须传入有效对象:
import * as yup from 'yup'; import { useForm, Controller } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import Select from 'react-select'; // Yup校验规则:先允许null,再强制要求提交时为有效对象 const schema = yup.object().shape({ category: yup .object({ label: yup.string().required("Tag is required"), value: yup.string().required("Tag is required"), }) .nullable() .required("Please select a category") // 阻止提交时为null }); // 表单初始化:无需手动传泛型,由Schema自动推导 const { control, handleSubmit } = useForm({ resolver: yupResolver(schema), defaultValues: { category: null, } }); // Controller使用示例 <Controller name="category" control={control} render={({ field, fieldState: { error } }) => ( <Select {...field} options={yourOptions} isClearable placeholder="Select category" error={!!error} helperText={error?.message} /> )} />
如果上述组合无法满足需求(如部分Yup版本中nullable后required逻辑异常),可使用自定义校验规则:
const schema = yup.object().shape({ category: yup .mixed() .nullable() .test( 'valid-category', 'Please select a valid category with label and value', (value) => { if (value === null) return false; // 不允许提交时为null // 校验对象结构 return yup.object({ label: yup.string().required(), value: yup.string().required(), }).isValidSync(value); } ) });
内容的提问来源于stack exchange,提问作者Ivomasterche
相关产品推荐
相关产品推荐

