
ag-grid 编辑单元格后调用 restore 仅生效一次,根本原因是直接复用引用的原始数据对象导致状态污染;需在每次恢复时创建深拷贝,确保数据隔离。
在使用 Ag-Grid(尤其是 React 版本)时,一个常见误区是:将初始数据保存为 useRef 引用后,在 restore 操作中直接赋值该引用——看似“还原”,实则因 React 组件内网格编辑会就地修改 rowData 中的对象属性(如 row.price = newValue),导致 initData.current 所指向的原始数组及其内部对象已被污染。
例如,初始数据为:
[{ make: 'Toyota', model: 'Celica', price: 35000 }]当用户编辑 Price 后,Ag-Grid 默认会直接修改该对象的 price 字段。若 initData.current 仍指向同一内存地址的对象,那么第一次 restore 虽然“看起来”恢复了,但此时 initData.current[0].price 已被改写;第二次 restore 实际恢复的是已被篡改过的“原始值”,造成失效假象。
✅ 正确做法:每次 restore 时生成原始数据的深拷贝,切断与已编辑数据的引用关联:
const restore = () => {
// 使用 JSON 序列化+反序列化实现轻量深拷贝(适用于纯JSON数据)
const freshCopy = JSON.parse(JSON.stringify(initData.current));
setRowData(freshCopy);
};⚠️ 注意事项:
- JSON.parse(JSON.stringify(obj)) 不适用于含函数、Date、undefined、RegExp 或循环引用的对象;若业务数据结构复杂,建议使用 lodash.cloneDeep 或自定义深克隆工具;
- 避免在 useEffect 中直接赋值 initData.current = data,而应始终通过 JSON.stringify 等方式初始化,确保初始快照纯净;
- 若启用了 Ag-Grid 的 immutableData: true 选项,则网格不会直接修改原始对象,此时可安全复用引用——但需同步开启 deltaRowDataMode: true 并配合 getRowNodeId 使用,适用场景有限。
总结:状态管理的核心在于不可变性(immutability)。Ag-Grid 的编辑行为默认是 mutable 的,因此开发者必须主动保障 restore 数据的“一次性新鲜度”。一句口诀:“恢复必深拷,引用不共享” —— 这是保障多次还原功能稳定可靠的底层准则。










