
ag-grid 编辑后多次点击“还原”按钮失效,根本原因是原始数据被直接引用并修改,导致 `initdata.current` 在首次还原后已非初始状态;需每次还原时创建深拷贝,而非复用已被污染的引用。
在使用 Ag-Grid 的 React 版本时,若需支持「编辑后一键还原至初始数据」功能,一个常见但易被忽视的陷阱是:对初始数据仅做一次浅层保存,后续还原却未隔离引用关系。如示例代码所示,initData.current = JSON.parse(JSON.stringify(data)) 确实在初始化时生成了深拷贝,但 restore() 函数中直接赋值 setRowData(initData.current) 会导致第二次还原时操作的是已被 Grid 内部或 React 状态更新间接修改过的同一对象引用(尤其当单元格编辑触发了对象属性变更且未强制克隆时)。
本质上,rowData 是受控的 React 状态,而 Ag-Grid 在编辑过程中可能直接修改传入的行对象(例如启用 immutableData={false} 默认行为),这会使 initData.current 所指向的对象在首次编辑后即被污染。因此,每次还原都必须生成全新的、独立的数据副本。
✅ 正确做法是在 restore 函数中即时执行深拷贝:
const restore = () => {
// 每次点击都创建全新深拷贝,确保与任何已有引用完全隔离
const freshCopy = JSON.parse(JSON.stringify(initData.current));
setRowData(freshCopy);
};⚠️ 注意事项:
- JSON.parse(JSON.stringify(obj)) 是快速深拷贝方案,适用于纯 JSON 数据(无函数、Date、undefined、RegExp、Map/Set 等)。若初始数据含复杂类型,请改用 structuredClone()(现代浏览器支持)或 Lodash 的 cloneDeep();
- 避免在 useEffect 外部或事件处理器中直接修改 rowData 数组或其内部对象——所有变更应通过 setRowData 触发新引用;
- 如需更高性能或更健壮的还原机制,可结合 onCellValueChanged 监听编辑动作,并维护一份不可变快照(如使用 Immer 或 Redux Toolkit)。
总结:Ag-Grid 的还原逻辑不是“重置引用”,而是“重置数据内容”。只要保证每次 setRowData 接收的都是与之前完全无关的新对象树,就能稳定实现多轮编辑→还原循环。










