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

React Ant Design可编辑表格:渲染时如何校验单元格数据?

React可编辑表格:渲染阶段校验与表格内提交校验实现

需求说明

我实现了一个React可编辑表格组件,需要满足两个校验需求:

  1. 组件渲染完成后,自动对所有可编辑单元格执行数据校验
  2. 提交操作在表格组件内部完成(不依赖外层Form),提交前需完成全量数据校验

以下是当前表格切换编辑状态的核心代码:

const EditableRow = ({index, ...props}) => {
    const [form] = Form.useForm();
    return (
        <Form form={form} component={false}>
            <EditableContext.Provider value={form}>
                <tr {...props} />
            </EditableContext.Provider>
        </Form>
    );
};

// ...

const toggleEdit = () => {
    setEditing(!editing);
    form.setFieldsValue({
        [dataIndex]: record[dataIndex],
    });
};

实现方案

1. 渲染阶段自动触发校验

每个可编辑行都持有独立的Form实例,利用useEffect在组件渲染完成后立即触发字段校验:

修改EditableRow组件:

const EditableRow = ({ index, record, ...props }) => {
  const [form] = Form.useForm();

  useEffect(() => {
    // 渲染完成后立即校验当前行所有可编辑字段
    form.validateFields();
  }, [form]);

  return (
    // 用record初始化表单值,替代手动setFieldsValue
    <Form form={form} component={false} initialValues={record}>
      <EditableContext.Provider value={form}>
        <tr {...props} />
      </EditableContext.Provider>
    </Form>
  );
};

同时调整toggleEdit函数,进入编辑模式时触发对应字段的校验:

const toggleEdit = () => {
  const newEditingState = !editing;
  setEditing(newEditingState);
  
  if (newEditingState) {
    form.setFieldsValue({ [dataIndex]: record[dataIndex] });
    // 仅校验当前切换的字段
    form.validateFields([dataIndex]);
  }
};

2. 表格内提交时全量校验

由于每行的Form实例独立,需先收集所有行的Form实例,再统一执行校验:

步骤1:创建Form实例收集容器

在表格父组件中创建ref存储所有行的Form实例,通过上下文传递给EditableRow:

import { createContext, useRef } from 'react';

// 创建上下文用于传递Form实例集合
const FormRefContext = createContext();

const EditableTable = () => {
  // 用Map存储行唯一标识与对应Form实例的映射
  const formRefs = useRef(new Map());

  return (
    <FormRefContext.Provider value={formRefs}>
      <Table
        components={{ body: { row: EditableRow } }}
        // 表格其他配置...
      />
      <button onClick={handleSubmit}>提交</button>
    </FormRefContext.Provider>
  );
};

步骤2:在EditableRow中注册Form实例

修改EditableRow,将当前行的Form实例存入全局容器:

import { useContext, useEffect } from 'react';

const EditableRow = ({ index, record, ...props }) => {
  const [form] = Form.useForm();
  const formRefs = useContext(FormRefContext);

  useEffect(() => {
    // 用record的唯一标识(如id)作为key存入Map
    const rowKey = record.id || index;
    formRefs.current.set(rowKey, form);
    
    // 渲染时触发校验
    form.validateFields();

    // 组件卸载时移除实例
    return () => formRefs.current.delete(rowKey);
  }, [form, record.id, index, formRefs]);

  return (
    <Form form={form} component={false} initialValues={record}>
      <EditableContext.Provider value={form}>
        <tr {...props} />
      </EditableContext.Provider>
    </Form>
  );
};

步骤3:实现提交时的全量校验

在表格父组件中编写提交函数,遍历所有Form实例执行校验:

const handleSubmit = async () => {
  let isAllValid = true;
  const errorRecords = [];

  // 遍历所有Form实例执行校验
  for (const [rowKey, form] of formRefs.current.entries()) {
    try {
      await form.validateFields();
    } catch (error) {
      isAllValid = false;
      errorRecords.push({ rowKey, error });
    }
  }

  if (isAllValid) {
    // 校验通过,收集所有行数据并提交
    const submitData = Array.from(formRefs.current.values()).map(form => form.getFieldsValue());
    // 这里替换为实际的提交逻辑(如调用接口)
    console.log('提交数据:', submitData);
  } else {
    // 校验失败,处理错误提示
    console.error('数据校验失败:', errorRecords);
    // 可以在这里给用户弹出提示,或标记错误行
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:37:18