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

如何为React Final Form嵌套输入编写正确的Zod验证Schema

动态增减输入项的表单Zod验证失效解决方法

问题核心原因

  1. Schema与表单字段不匹配:你定义的Zod Schema里,field是包含label和value的对象,但表单中field是单选框的字符串值;conditions被定义为空对象,实际表单里是字符串值,还遗漏了表单中存在的operator字段定义。
  2. 遍历参数错误:filterList.map((index) => ...)写法错误,map的第一个参数是数组元素,第二个才是索引,会导致字段命名的索引逻辑出错。
  3. 未设置必填约束:仅定义了数据结构,未给字段添加min(1)或required()这类触发验证的规则,自然不会出现提示。

修正后的完整代码

import { useState } from 'react';
import { z } from 'zod';

const DynamicFilterForm = ({ initialValues = [] }) => {
  // 修正初始值判断逻辑,避免数组引用比较的错误
  const [filterList, setFilterList] = useState(
    initialValues.length > 0 ? initialValues : [{ operator: "", field: "", conditions: "" }]
  );

  // 匹配表单实际字段的Zod验证规则
  const verifyInput = () => {
    return z.object({
      filters: z.array(
        z.object({
          operator: z.string().min(1, "操作符不能为空"),
          field: z.string().min(1, "请选择字段"),
          conditions: z.string().min(1, "请选择条件"),
        })
      ).min(1, "至少需要添加一个筛选条件"),
    });
  };

  const handleFilterAdd = () => {
    setFilterList([...filterList, { operator: "", field: "", conditions: "" }]);
  };

  const handleFilterRemoveAll = () => {
    setFilterList([{ operator: "", field: "", conditions: "" }]);
  };

  return (
    <Form schema={verifyInput()}>
      {filterList.map((_, index) => (
        <div key={index}>
          <input
            id={`operator-${index}`}
            name={`filters[${index}].operator`}
            size="sm"
            type="text"
            placeholder="输入操作符"
          />

          <select
            id={`field-${index}`}
            name={`filters[${index}].field`}
            placeholder="选择字段"
          >
            <option value="">请选择</option>
            <option value="volvo">Volvo</option>
            <option value="saab">Saab</option>
          </select>

          <select
            id={`conditions-${index}`}
            size="sm"
            name={`filters[${index}].conditions`}
            placeholder="选择条件"
          >
            <option value="">请选择</option>
            <option value="mercedes">Mercedes</option>
            <option value="audi">Audi</option>
          </select>
        </div>
      ))}
      <RemoveAllFiltersButton handleFilterRemoveAll={handleFilterRemoveAll} />
      <Button onClick={handleFilterAdd} leftIcon={<FiPlus />}>
        Add Filter
      </Button>
    </Form>
  );
};

export default DynamicFilterForm;

关键优化点

  • 给下拉框添加空选项,确保未选择时能触发必填验证;
  • 为每个字段添加自定义错误提示,明确验证要求;
  • 给filters数组添加min(1)约束,保证至少存在一个筛选项;
  • 修正了filterList初始化时的逻辑错误,避免无效判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:43:22