探索 React 浅复制方法:扩展运算符与直接赋值

问题描述 投票:0回答:1

我目前正在开发一个 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>&nbsp;<span style={{ fontStyle: 'italic' }}>output</span>
                            </Link>
                        </div>
                    </Form>
                </div>
            </div>
        );
    
    };

另外,我在flux.js

行动
是:

updateEmail: (newData) => {
                setStore({
                    ...getStore(),
                    email: {
                        ...getStore().email,
                        ...newData,
                    }
                });
            },

任何见解或解释将不胜感激。谢谢!

javascript reactjs javascript-objects shallow-copy spread-syntax
1个回答
0
投票

好的!让我们开始分析(注意:可能有很多东西需要阅读)

方法一:

考虑一个物体,

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,它传递你的完整对象。

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.