深度克隆具有react元素的对象会破坏该元素,您将无法再渲染该元素,Here is an example showing this issue
import React from "react";
import "./styles.css";
import Demo from "./Demo";
export default function App() {
const test = <div>I'm a react element</div>;
console.log("test", test);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Demo obj={{ element: test }} />
</div>
);
}
// Demo.js
import React from "react";
// import cloneDeep from "lodash.clonedeep";
import CloneDeep from "clone-deep";
const Demo = ({ obj }) => {
const newProps = CloneDeep(obj);
console.log(newProps.element);
// console.log("Demo element", newProps.element);
return (
<div>
I'm Demo Component
{newProps.element}
</div>
);
};
export default Demo;
我还尝试了其他几个深度克隆库,但在我看来它们都不起作用!所以您知道一个这样做的库吗?或者也许我可以通过做一些事情来修复当前的克隆库?还是我可以写自己的深克隆内容,对此有何建议?到目前为止我尝试过的是:1-使用import CloneDeep from "clone-deep";
将导致objects are not valid as a react child
错误2-使用import cloneDeep from "lodash.clonedeep";
,该错误与先前的库没有相同的错误,但是会引发infinity loop, Max Stack
错误!谢谢。
我去了github
clone-deep
复制了他们的代码并进行了一些更改1-首先我使用React.isValidElement
检查该值是否为react元素2-感谢@warmachine我使用React.cloneElement
如果对象是用于克隆对象的react元素,否则,我会执行库始终执行的操作
在这里您可以看到完整的代码:
import React from "react";
const clone = require("shallow-clone");
const typeOf = require("kind-of");
const isPlainObject = require("is-plain-object");
export function cloneDeep(val, instanceClone) {
if (React.isValidElement(val)) {
return React.cloneElement(val);
} else {
const valueType = typeOf(val);
switch (valueType) {
case "object":
return cloneObjectDeep(val, instanceClone);
case "array":
return cloneArrayDeep(val, instanceClone);
default: {
return clone(val);
}
}
}
}
function cloneObjectDeep(val, instanceClone) {
if (typeof instanceClone === "function") {
return instanceClone(val);
}
if (instanceClone || isPlainObject(val)) {
const res = new val.constructor();
for (let key in val) {
res[key] = cloneDeep(val[key], instanceClone);
}
return res;
}
return val;
}
function cloneArrayDeep(val, instanceClone) {
const res = new val.constructor(val.length);
for (let i = 0; i < val.length; i++) {
res[i] = cloneDeep(val[i], instanceClone);
}
return res;
}