我目前正在开发一个 React 项目,遇到了一个与浅复制对象相关的有趣问题。在我的组件中,我有一个收集数据的表单,我注意到浅复制数据对象的不同方法会导致不同的行为。
以下是我尝试过的三种方法:
方法 1(有效)
const handleSubmit = async (e) => {
e.preventDefault();
actions.updateEmail(...Object.values(localEmailData));
console.log(store);
};
方法 2(有效,但控制台错误)
const handleSubmit = async (e) => {
e.preventDefault();
actions.updateEmail(...localEmailData);
console.log(store);
};
控制台错误显示:
Uncaught (in promise) TypeError: Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.
方法3(行不通)
const handleSubmit = async (e) => {
e.preventDefault();
actions.updateEmail(localEmailData);
console.log(store);
};
有人可以解释一下这些方法之间的差异,以及为什么方法 2 虽然有效,但会触发控制台错误?另外,为什么方法 3 不起作用?
我的 React 组件
[…]
export const Home = () => {
const { store, actions } = useContext(Context);
const [localEmailData, setLocalEmailData] = useState({
projectName: store.email.nombreDelProyecto,
unsubscribeUrl: store.email.unsubscribeUrl,
header: {
link1: store.email.header.link1,
image1: store.email.header.image1,
alt1: store.email.header.alt1,
link2: store.email.header.link2,
image2: store.email.header.image2,
alt2: store.email.header.alt2,
link3: store.email.header.link3,
image3: store.email.header.image3,
alt3: store.email.header.alt3,
},
cta: {
image: store.email.cta.image,
link: store.email.cta.link,
},[…]
});
const handleInputChange = (e) => {
setLocalEmailData({ localEmailData, [e.target.name]: e.target.value });
console.log("localEmailData", localEmailData);
console.log("Submitting form with data:", localEmailData);
};
const handleSubmit = async (e) => {
e.preventDefault();
actions.updateEmail(...Object.values(localEmailData));
console.log(store);
};
return (
<div className="mt-5">
<div className="d-flex justify-content-center">
{/* Formulario de encabezado */}
<Form className="w-50" onSubmit={handleSubmit}>
[…]
<div className="d-flex justify-content-center">
<Button type="submit" className="generar-correo">
Validate & Generate
</Button>
<Link to="/pocuromailbuilder" className="generar-correo">
<span>Go to </span> <span style={{ fontStyle: 'italic' }}>output</span>
</Link>
</div>
</Form>
</div>
</div>
);
};
另外,我在flux.js
的
行动是:
updateEmail: (newData) => {
setStore({
...getStore(),
email: {
...getStore().email,
...newData,
}
});
},
任何见解或解释将不胜感激。谢谢!
好的!让我们开始分析(注意:可能有很多东西需要阅读)
方法一:
考虑一个物体,
let testObject = {
key1:value1,
key2:value2,
key3:value3
}
// When Object.values(testObject) is applied it returns an array with object's
// Property Values eg: [value1,value2,value3]
// and when spread operator is applied, it expands the array and throws the
// elements out eg: ...[value1, value2, value3] becomes value1 value2 value3
接受扩展语法的三个地方是函数参数、数组和对象文字。只有可迭代值(数组或字符串)才能进入前两个位置,即函数参数和数组文字。
方法2:
现在你知道我们只有 3 个地方可以使用扩展语法。就像你的第二个例子,如果我申请的话,
console.log(...testObject) // expands the object and each property is printed
// The catch here is that the console log function takes the expanded values
// and logs them, returns void and the spread operation expanded the values thinking that the
// values goes into any of the 3 places mentioned above. **But it did not hence error.**
添加 {...testObject},对象字面量有效或使用 [Symbol.iterator]
现在你可以连接它来结束方法3,它传递你的完整对象。
希望这有帮助!