You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:00:26