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

如何在react-final-form中设置数组字段的错误?求验证示例

没问题!我来帮你搞定react-final-form里数组字段的错误提示和验证规则设置~针对你提到的场景,我已经整理好了完整的实现方案,下面是具体内容:

数组字段验证与错误提示实现

1. 编写全局验证函数

首先我们需要定义一个验证函数,它会遍历数组中的每一项,为每个子字段添加对应的错误规则:

const validate = (values) => {
  const errors = {};
  // 检查contacts数组是否存在
  if (values.contacts) {
    errors.contacts = [];
    values.contacts.forEach((contact, index) => {
      const contactErrors = {};
      // 姓名必填验证(去除首尾空格)
      if (!contact.name?.trim()) {
        contactErrors.name = "姓名不能为空";
      }
      // 邮箱格式验证(有输入时才校验格式)
      if (contact.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(contact.email)) {
        contactErrors.email = "请输入有效的邮箱地址";
      }
      // 如果当前项有错误,添加到errors数组对应索引位置
      if (Object.keys(contactErrors).length > 0) {
        errors.contacts[index] = contactErrors;
      }
    });
  }
  return errors;
};

2. 为数组子字段添加错误提示

在FieldArray的渲染函数中,每个子字段(姓名、邮箱)需要通过meta.error获取对应错误,结合meta.touched判断是否显示错误提示(避免页面加载就显示错误,只有用户触碰过字段后才展示):

<FieldArray name="contacts">
  {({ fields }) => (
    <div>
      {fields.map((name, index) => (
        <div key={name} style={{ marginBottom: "1rem" }}>
          <Field name={`contacts[${index}].name`}>
            {({ input, meta }) => (
              <div>
                <label>姓名</label>
                <input {...input} placeholder="请输入姓名" />
                {/* 显示姓名字段错误 */}
                {meta.error && meta.touched && (
                  <span style={{ color: "red", fontSize: "0.8rem" }}>
                    {meta.error}
                  </span>
                )}
              </div>
            )}
          </Field>
          <Field name={`contacts[${index}].email`}>
            {({ input, meta }) => (
              <div>
                <label>邮箱</label>
                <input {...input} placeholder="请输入邮箱" />
                {/* 显示邮箱字段错误 */}
                {meta.error && meta.touched && (
                  <span style={{ color: "red", fontSize: "0.8rem" }}>
                    {meta.error}
                  </span>
                )}
              </div>
            )}
          </Field>
          <button
            type="button"
            onClick={() => fields.remove(index)}
            style={{ marginTop: "0.5rem" }}
          >
            删除联系人
          </button>
        </div>
      ))}
      <button
        type="button"
        onClick={() => fields.push({ name: "", email: "" })}
      >
        添加联系人
      </button>
    </div>
  )}
</FieldArray>

3. 将验证函数传入Form组件

最后把我们写好的validate函数传给Form组件的validate属性,这样表单提交或者字段值变化时就会自动触发验证:

<Form
  onSubmit={onSubmit}
  validate={validate}
  initialValues={{ contacts: [{ name: "", email: "" }] }}
>
  {({ handleSubmit, values }) => (
    <form onSubmit={handleSubmit}>
      {/* 上面的FieldArray代码 */}
      <button type="submit">提交</button>
      <pre>{JSON.stringify(values, 0, 2)}</pre>
    </form>
  )}
</Form>
完整可运行代码示例
import React from "react";
import { Form, Field, FieldArray } from "react-final-form";

const onSubmit = (values) => {
  alert(JSON.stringify(values, 0, 2));
};

const validate = (values) => {
  const errors = {};
  if (values.contacts) {
    errors.contacts = [];
    values.contacts.forEach((contact, index) => {
      const contactErrors = {};
      if (!contact.name?.trim()) {
        contactErrors.name = "姓名不能为空";
      }
      if (contact.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(contact.email)) {
        contactErrors.email = "请输入有效的邮箱地址";
      }
      if (Object.keys(contactErrors).length > 0) {
        errors.contacts[index] = contactErrors;
      }
    });
  }
  return errors;
};

const App = () => (
  <div style={{ maxWidth: 600, margin: "0 auto", padding: "2rem" }}>
    <h1>联系人表单(带数组字段验证)</h1>
    <Form
      onSubmit={onSubmit}
      validate={validate}
      initialValues={{ contacts: [{ name: "", email: "" }] }}
    >
      {({ handleSubmit, values }) => (
        <form onSubmit={handleSubmit}>
          <FieldArray name="contacts">
            {({ fields }) => (
              <div>
                {fields.map((name, index) => (
                  <div key={name} style={{ marginBottom: "1.5rem" }}>
                    <h3>联系人 #{index + 1}</h3>
                    <Field name={`contacts[${index}].name`}>
                      {({ input, meta }) => (
                        <div style={{ marginBottom: "0.5rem" }}>
                          <label style={{ display: "block", marginBottom: "0.2rem" }}>姓名</label>
                          <input
                            {...input}
                            placeholder="请输入姓名"
                            style={{ padding: "0.5rem", width: "100%" }}
                          />
                          {meta.error && meta.touched && (
                            <span style={{ color: "red", fontSize: "0.8rem" }}>
                              {meta.error}
                            </span>
                          )}
                        </div>
                      )}
                    </Field>
                    <Field name={`contacts[${index}].email`}>
                      {({ input, meta }) => (
                        <div style={{ marginBottom: "0.5rem" }}>
                          <label style={{ display: "block", marginBottom: "0.2rem" }}>邮箱</label>
                          <input
                            {...input}
                            placeholder="请输入邮箱"
                            style={{ padding: "0.5rem", width: "100%" }}
                          />
                          {meta.error && meta.touched && (
                            <span style={{ color: "red", fontSize: "0.8rem" }}>
                              {meta.error}
                            </span>
                          )}
                        </div>
                      )}
                    </Field>
                    <button
                      type="button"
                      onClick={() => fields.remove(index)}
                      style={{ padding: "0.3rem 0.8rem", backgroundColor: "#ff4444", color: "white", border: "none", borderRadius: "4px" }}
                    >
                      删除联系人
                    </button>
                  </div>
                ))}
                <button
                  type="button"
                  onClick={() => fields.push({ name: "", email: "" })}
                  style={{ padding: "0.5rem 1rem", backgroundColor: "#00C851", color: "white", border: "none", borderRadius: "4px" }}
                >
                  添加联系人
                </button>
              </div>
            )}
          </FieldArray>
          <div style={{ marginTop: "2rem" }}>
            <button
              type="submit"
              style={{ padding: "0.5rem 1.5rem", backgroundColor: "#33b5e5", color: "white", border: "none", borderRadius: "4px" }}
            >
              提交表单
            </button>
          </div>
          <div style={{ marginTop: "2rem" }}>
            <h3>当前表单值:</h3>
            <pre>{JSON.stringify(values, 0, 2)}</pre>
          </div>
        </form>
      )}
    </Form>
  </div>
);

export default App;

这样修改后,每个数组项的姓名和邮箱字段都会有对应的验证规则,错误提示会在用户触碰字段且不符合规则时显示,提交表单时也会触发全局验证,确保所有字段都符合要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:33:20