
本文介绍在 react 中深拷贝嵌套对象的实用方法,重点解决表单输入清空时需回退到初始值的场景,涵盖 `json.parse(json.stringify())`、结构化克隆 api 及自定义工具函数等方案,并强调不可变更新与性能注意事项。
在 React 应用中,直接修改 state 对象(如 stateObj.option.c = newValue)会破坏不可变性原则,导致渲染异常或副作用难以追踪。尤其当需要在用户清空输入框时「恢复原始值」时,必须确保初始嵌套对象被完全独立克隆,而非仅复制引用。
✅ 推荐方案:使用 useRef + 深拷贝初始化
以下是一个完整、可运行的示例:
import React, { useState, useEffect, useRef } from 'react';
function FormComponent({ onChange }) {
const [stateObj, setStateObj] = useState({
a: "one",
b: 2,
option: {
c: "value",
d: { nested: true }
}
});
// 使用 useRef 安全保存初始 option 的深拷贝(仅在挂载时执行一次)
const originalOption = useRef(null);
useEffect(() => {
// ✅ 安全深拷贝:支持多层嵌套(但不支持函数、Date、RegExp、undefined、Symbol 等)
originalOption.current = JSON.parse(JSON.stringify(stateObj.option));
}, []);
const handleInputChange = (path, value) => {
if (value === '') {
// 清空时还原整个 option 对象(非仅 c 字段,确保一致性)
setStateObj(prev => ({
...prev,
option: { ...originalOption.current } // 再次浅拷贝以确保新引用
}));
onChange?.(path, originalOption.current.c);
} else {
// 更新指定路径(简化版:仅支持两级如 ["option", "c"])
setStateObj(prev => {
const newState = { ...prev };
const [parentKey, childKey] = path;
if (newState[parentKey] && typeof newState[parentKey] === 'object') {
newState[parentKey] = {
...newState[parentKey],
[childKey]: value
};
}
return newState;
});
onChange?.(path, value);
}
};
return (
handleInputChange(['option', 'c'], e.target.value)}
onBlur={(e) => {
if (e.target.value === '') {
handleInputChange(['option', 'c'], '');
}
}}
placeholder="编辑后留空可恢复初始值"
/>
);
}
export default FormComponent;⚠️ 注意事项与替代方案
| 方法 | 适用场景 | 局限性 | 推荐指数 |
|---|---|---|---|
| JSON.parse(JSON.stringify(obj)) | 快速原型、纯数据对象(无函数/Date/循环引用) | ❌ 不支持 undefined、function、Date、RegExp、Map、Set、BigInt、Symbol;会丢失原型链 | ⭐⭐⭐⭐ |
| structuredClone()(现代浏览器) | 需要完整类型保真(Chrome 98+ / Firefox 94+) | ❌ IE 不支持,Node.js | ⭐⭐⭐⭐⭐ |
| Lodash _.cloneDeep() | 企业级项目,需稳定兼容性 | ⚠️ 增加包体积(约 7KB gzip) | ⭐⭐⭐⭐ |
| 自定义递归克隆函数 | 极简依赖要求,可控性强 | ⚠️ 易遗漏边界情况(如循环引用、特殊对象) | ⭐⭐⭐ |
? 关键提醒: useRef 本身不触发重渲染,适合存储持久不变的初始快照; 即使 originalOption.current 是深拷贝,setStateObj 中仍需用 { ...originalOption.current } 浅拷贝,确保 React 检测到引用变化; 若 state 结构复杂(如含数组、深层嵌套),建议封装通用 setIn / getIn 工具函数,或采用 Immer 简化不可变更新逻辑。
✅ 总结
克隆 React state 中的嵌套对象,核心在于深拷贝 + 引用隔离。对于大多数表单场景,useRef + JSON.parse(JSON.stringify()) 组合简洁可靠;对高保真需求,优先选用 structuredClone();长期维护项目可引入 Immer 实现“直觉式”不可变更新。始终牢记:永远不要直接修改 state 对象,所有更新都应返回新引用。










