
aggrid 中点击“还原”按钮无法多次恢复原始数据,是因为直接引用了被修改的原始数据对象;需通过深拷贝创建独立副本,确保每次还原都基于初始快照。
在使用 AgGrid 实现可编辑表格时,一个常见需求是提供「还原原始数据」功能。但如示例所示,首次点击还原按钮可成功回退,再次编辑后却失效——根本原因在于:initData.current 存储的是对原始数组的浅引用,而 AgGrid 在编辑单元格(如 price 字段)时,会直接修改 rowData 中的对象属性。由于 JavaScript 对象是引用类型,这些修改会同步反映到 initData.current 所指向的同一内存地址上,导致“原始数据”在第一次编辑后即被污染。
✅ 正确做法:每次还原前生成深拷贝
你不能直接 setRowData(initData.current),而应始终基于初始数据的不可变副本进行还原:
const restore = () => {
// 使用 JSON 序列化+反序列化实现简易深拷贝(适用于纯JSON数据)
const freshCopy = JSON.parse(JSON.stringify(initData.current));
setRowData(freshCopy);
};⚠️ 注意:JSON.parse(JSON.stringify(obj)) 是一种轻量级深拷贝方式,适用于不含函数、undefined、Date、RegExp、Map/Set 等特殊类型的纯数据对象。若你的原始数据结构更复杂,建议使用 lodash.cloneDeep() 或结构化克隆(structuredClone(),现代浏览器支持):// 更健壮的替代方案(推荐生产环境) const freshCopy = structuredClone(initData.current); // 或:import { cloneDeep } from 'lodash'; const freshCopy = cloneDeep(initData.current);
? 补充优化建议
-
初始化时机要可靠:useEffect 中调用异步 Promise 时,应添加清理机制防止状态更新在组件卸载后执行(避免警告或异常),例如:
useEffect(() => { let isMounted = true; myPromise.then(data => { if (isMounted) { setRowData(data); initData.current = structuredClone(data); // 初始化即深拷贝,更安全 } }); return () => { isMounted = false; }; }, []); 避免重复渲染陷阱:确保 initData.current 仅在初始加载时赋值一次,且不参与 useState 或 useEffect 依赖数组,否则可能触发意外重置。
UI 反馈增强:可在 restore 按钮中添加禁用态或加载提示,提升用户体验,例如结合 useState 控制按钮状态。
通过强制每次还原都使用全新数据实例,即可彻底解决 AgGrid 多次编辑后无法还原的问题——核心原则始终是:原始数据必须 Immutable(不可变)。











