Antd Form如何检测初始值变更以控制重置按钮的条件渲染
Antd Form 检测值与初始值差异的实现方案
Antd Form 没有直接暴露"当前表单值较初始值是否修改"的内置标识,完全可以通过「初始值快照存储 + 值对比」的成熟逻辑实现需求,不需要依赖特殊第三方库。
基础实现逻辑
- 表单初始化时,把配置的初始值做深拷贝,存在ref中作为固定的对比基准,避免初始值被后续操作修改、组件重渲染时引用变化导致对比误判
- 通过Form组件的
onValuesChange回调,接收每一次表单变更后的全量表单数据 - 对当前全量值和存储的初始快照做深相等对比,只要任意字段存在取值差异,就更新状态值,用于控制重置按钮的条件渲染
参考代码片段
import { Form, Button } from 'antd'; import { useRef, useState } from 'react'; import { isEqual, cloneDeep } from 'lodash'; // 可替换为自研的轻量深对比工具,无第三方依赖也可实现 const ProfileForm = () => { const [form] = Form.useForm(); // 存储初始值快照的ref const initialSnapshotRef = useRef(null); const [isFormDirty, setIsFormDirty] = useState(false); // 表单配置的初始值 const defaultValues = { username: 'guest', age: 20, notifyEnabled: true }; // 组件首次渲染时初始化快照 if (!initialSnapshotRef.current) { initialSnapshotRef.current = cloneDeep(defaultValues); } // 表单值变更回调 const handleFormChange = (_, allFormValues) => { // 深对比当前值和初始快照,判断是否有差异 const hasDiff = !isEqual(allFormValues, initialSnapshotRef.current); setIsFormDirty(hasDiff); }; // 重置按钮逻辑 const handleClickReset = () => { // 手动将表单值恢复为初始快照 form.setFieldsValue(cloneDeep(initialSnapshotRef.current)); setIsFormDirty(false); }; return ( <Form form={form} initialValues={defaultValues} onValuesChange={handleFormChange} > {/* 业务表单字段省略 */} {isFormDirty && ( <Button onClick={handleClickReset}>重置</Button> )} <Button type="primary" htmlType="submit">保存</Button> </Form> ); };
大表单场景的性能优化
对于字段数量多、输入交互频繁的大表单,每一次值变更都触发状态更新会带来不必要的重渲染,可通过两种方式优化:
- 给对比逻辑加300ms左右的防抖,等用户输入停顿后再做值对比、更新状态,减少高频输入过程中的无意义渲染
- 取消全局onValuesChange的实时监听,只在需要判断按钮显示的节点(比如表单值加载完成后、用户切换表单焦点时),主动调用
form.getFieldsValue()获取全量值与初始快照对比,更新修改状态
开发踩坑提醒
- 不要用浅对比判断值是否一致,嵌套结构的表单字段容易因为引用问题出现判断失误
- 不要直接依赖Antd内置的
form.resetFields方法实现重置:该方法的恢复基准是Form组件首次挂载时的initialValues,如果存在异步加载初始值的场景,内置方法的恢复值会和实际预期的初始值不匹配,手动通过setFieldsValue恢复更可控 - 不要用
JSON.stringify做值对比,该方法会忽略undefined、函数、Symbol类型的字段,容易出现对比误判
内容的提问来源于stack exchange,提问作者jason135
相关产品推荐
相关产品推荐

