Yup校验结合useFieldArray时如何访问表单全局pageId值
解决Yup数组项校验中访问根表单字段的问题
方法一:利用Yup上下文的parent层级获取全局pageId
在数组项的test函数中,可通过this.parent.parent获取整个根表单对象,从而拿到pageId值。修改后的schema代码如下:
export const schema = (user: User) => Yup.object().shape({ name: Yup.string().required('Enter a name'), websiteId: Yup.string().required('Select a website'), pageId: Yup.string().required('Select a page'), variants: Yup.array() .of( Yup.object() .shape({ name: Yup.string().required('Enter a variant name'), pageRedirectId: Yup.string(), }) .test( 'redirects to the same page', 'You cannot redirect to the same page. Choose a different page to redirect to', function (value, ctx) { const { pageRedirectId } = value; // 获取根表单对象,variants的父级即为整个表单 const formValues = this.parent.parent; const pageId = formValues.pageId; // 自动获取当前字段路径,无需手动拼接 const path = `${this.path}.pageRedirectId`; // 仅当pageRedirectId存在且与pageId相同时触发错误 if (pageRedirectId && pageRedirectId === pageId) { return this.createError({ message: 'A variant cannot have the same page redirect as the main page', path, }); } return true; } ) ) .min(2, 'At least one variant is required') .required('Add at least one variant') });
this.parent指向当前数组项所在的variants数组,this.parent.parent则是整个根表单对象,包含pageId字段- 使用
this.path自动获取当前数组项的路径,避免手动拼接索引可能出现的错误 - 增加
pageRedirectId存在性判断,避免undefined与pageId比较的无效校验
方法二:将pageId作为参数传入schema函数
如果方法一中的层级引用存在兼容性问题,可将pageId作为参数传入schema生成函数,结合react-hook-form的watch动态更新校验规则:
第一步:修改schema函数
export const schema = (user: User, pageId?: string) => Yup.object().shape({ name: Yup.string().required('Enter a name'), websiteId: Yup.string().required('Select a website'), pageId: Yup.string().required('Select a page'), variants: Yup.array() .of( Yup.object() .shape({ name: Yup.string().required('Enter a variant name'), pageRedirectId: Yup.string(), }) .test( 'redirects to the same page', 'You cannot redirect to the same page. Choose a different page to redirect to', function (value) { const { pageRedirectId } = value; // 若pageId未初始化则跳过校验 if (!pageId) return true; if (pageRedirectId === pageId) { return this.createError({ message: 'A variant cannot have the same page redirect as the main page', path: `${this.path}.pageRedirectId`, }); } return true; } ) ) .min(2, 'At least one variant is required') .required('Add at least one variant') });
第二步:在组件中动态生成schema
import { useForm, watch, useMemo } from 'react-hook-form'; import { schema } from './your-schema-path'; // 假设user已从上下文或props获取 const user = /* 获取user的逻辑 */; function YourFormComponent() { const { control, register, formState: { errors } } = useForm({ defaultValues: { name: '', websiteId: '', pageId: '', variants: [{ name: '', pageRedirectId: '' }, { name: '', pageRedirectId: '' }] } }); // 监听pageId字段的变化 const pageId = watch('pageId'); // 当user或pageId变化时重新生成schema const validationSchema = useMemo(() => schema(user, pageId), [user, pageId]); return ( <div> {/* 其他表单字段 */} <input {...register('pageId')} /> {/* useFieldArray相关渲染逻辑 */} </div> ); }
- 通过
watch监听pageId的变化,确保schema始终使用最新的pageId值 - 使用
useMemo避免不必要的schema重新生成,提升性能
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

