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

React Hook Form结合Yup resolver处理动态GUID字段验证问题

解决动态GUID字段的React Hook Form + Yup验证问题

针对后端动态生成的GUID字段表单,无法提前构建Yup Schema的问题,可通过动态构建Schema并延迟设置Resolver的方式实现复杂验证,具体方案如下:

方法一:基于后端配置动态生成Yup Schema

1. 准备后端表单配置

假设后端返回包含字段GUID、类型、验证规则的配置数组:

// 示例后端返回的表单配置
const formConfig = [
  {
    guid: "6c6f1869-73ae-447b-b893-a089db54d057",
    type: "radio",
    options: [
      { guid: "c2f7ae0d-0f1b-474b-a98a-2c54e17670b9", label: "选项1" },
      { guid: "d3f8bf0e-1f2c-585c-b09b-3d55f27701c0", label: "选项2" }
    ],
    validation: {
      required: "请选择一个选项",
      validOption: "请选择有效的选项"
    }
  },
  // 其他动态字段配置
];

2. 编写Schema构建函数

遍历配置数组,为每个GUID字段生成对应的Yup验证规则:

import * as yup from "yup";

const buildYupSchema = (config) => {
  const schemaShape = {};
  
  config.forEach(field => {
    // 根据字段类型初始化基础Schema
    let fieldSchema = field.type === "number" ? yup.number() : yup.string();
    
    // 添加必填规则
    if (field.validation.required) {
      fieldSchema = fieldSchema.required(field.validation.required);
    }
    
    // 添加自定义验证(比如单选框选项有效性校验)
    if (field.type === "radio") {
      fieldSchema = fieldSchema.test(
        "valid-option",
        field.validation.validOption,
        (value) => field.options.some(opt => opt.guid === value)
      );
    }
    
    schemaShape[field.guid] = fieldSchema;
  });
  
  return yup.object().shape(schemaShape);
};

3. 在组件中动态设置Resolver

通过useEffect获取后端配置后,构建Schema并更新React Hook Form的Resolver:

import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import { useEffect, useState } from "react";

const DynamicGUIDForm = () => {
  const [formConfig, setFormConfig] = useState(null);
  const { register, handleSubmit, setResolver, formState: { errors } } = useForm();

  // 模拟从后端获取表单配置
  useEffect(() => {
    fetch("/api/form-config")
      .then(res => res.json())
      .then(config => {
        setFormConfig(config);
        // 构建Schema并设置Resolver
        const validationSchema = buildYupSchema(config);
        setResolver(yupResolver(validationSchema));
      });
  }, []);

  const onSubmit = (data) => {
    console.log("提交数据:", data);
  };

  if (!formConfig) return <div>加载表单中...</div>;

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {formConfig.map(field => (
        <div key={field.guid} className="form-group">
          {field.options.map(option => (
            <label key={option.guid}>
              <input
                type="radio"
                value={option.guid}
                {...register(field.guid)}
              />
              {option.label}
            </label>
          ))}
          {/* 显示验证错误 */}
          {errors[field.guid] && <span className="error">{errors[field.guid].message}</span>}
        </div>
      ))}
      <button type="submit">提交</button>
    </form>
  );
};

export default DynamicGUIDForm;

方法二:使用Yup.lazy延迟生成Schema

如果无法提前获取后端配置,可通过yup.lazy在验证时动态生成规则(需结合表单提交数据的字段结构):

import * as yup from "yup";

// 假设已通过其他方式获取到所有可能的字段配置
const allFieldConfigs = [/* 所有动态字段的配置 */];

const dynamicSchema = yup.object().shape({
  [yup.lazy((formData) => {
    const schemaShape = {};
    // 遍历提交数据中的GUID字段,匹配配置生成规则
    Object.keys(formData).forEach(guid => {
      const fieldConfig = allFieldConfigs.find(f => f.guid === guid);
      if (fieldConfig) {
        let fieldSchema = yup.string().required("此字段为必填项");
        // 添加其他自定义规则
        schemaShape[guid] = fieldSchema;
      }
    });
    return yup.object().shape(schemaShape);
  })]: yup.any()
});

关键注意事项

  • 确保后端返回的配置包含足够的验证元信息(如必填提示、自定义校验逻辑参数)
  • 根据字段类型选择对应的Yup基础类型(如数字字段用yup.number(),文本字段用yup.string())
  • 使用setResolver方法可在组件挂载后动态更新验证规则,无需重新初始化useForm

内容的提问来源于stack exchange,提问作者noblerare

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:36:13