React Ant Design可编辑表格:渲染时如何校验单元格数据?
React可编辑表格:渲染阶段校验与表格内提交校验实现
需求说明
我实现了一个React可编辑表格组件,需要满足两个校验需求:
- 组件渲染完成后,自动对所有可编辑单元格执行数据校验
- 提交操作在表格组件内部完成(不依赖外层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
相关产品推荐
相关产品推荐

