Javascript 在不使用扩展运算符的情况下正确更新React.js状态下的对象

Javascript 在不使用扩展运算符的情况下正确更新React.js状态下的对象,javascript,reactjs,Javascript,Reactjs,根据Visual Studio或ReSharper Intellisense,spread操作符…是一种实验级功能,我正在使用ECMAScript 2015: 我正在使用Babel,我在传输源中看到了spread运算符: 所以我试图用object.assign替换spread操作符功能,以更新处于React状态的对象 使用“扩展”操作符,我可以使用以下内容更新对象的状态: setInputs(prevInputs => ({ ...prevInputs, [name]:value}))

根据Visual Studio或ReSharper Intellisense,spread操作符
是一种实验级功能,我正在使用ECMAScript 2015:

我正在使用Babel,我在传输源中看到了spread运算符:

所以我试图用object.assign替换spread操作符功能,以更新处于React状态的对象

使用“扩展”操作符,我可以使用以下内容更新对象的状态:

setInputs(prevInputs => ({ ...prevInputs, [name]:value}));
这很有效。现在我想删除spread操作符以最大限度地提高跨浏览器兼容性

不幸的是,当我尝试使用其他方法更新状态对象中属性的值更改时,会出现错误:

组件正在将文本类型的受控输入更改为非受控输入。输入元件不应从受控切换到非受控

我理解此错误消息的含义,我无法理解的是我的对象更新与扩展运算符有什么不同,以下是我尝试替换扩展运算符的方法:

if (value) {
    //try to update state with value that is not undefined
    setInputs(prevInputs => Object.assign({}, prevInputs)[name] = value);

    //another try to update state with value that is not undefined
    setInputs(prevInputs => prevInputs[name] = value);
}
我不明白这里发生了什么,spread操作符正在创建一个新对象:

const originalObj = {
    name: '',
};
const spread = {...originalObj};
console.log('is originalObj === spread', originalObj === spread); //no they are not

my Object.assign替换排列而不是关闭的方式如何模拟排列操作符对象创建?

要模拟排列并为对象指定新属性,您需要

(1) 创建原始对象的浅层副本

(2) 为复制的对象指定新值

(3) 返回复制的对象

当你这样做的时候

setInputs(prevInputs => Object.assign({}, prevInputs)[name] = value);
您正在创建一个浅复制,但随后返回赋值,因此返回值是赋值的值,而不是复制的对象。上述代码相当于

setInputs(prevInputs => value);
setInputs(prevInputs => {
  prevInputs[name] = value;
  return value;
});
最好避免在表达式中使用赋值-它们几乎从来都不是你想要的

您所做的有点类似:您正在对现有的
prevInputs
对象进行变异,并返回
值。相当于

setInputs(prevInputs => value);
setInputs(prevInputs => {
  prevInputs[name] = value;
  return value;
});
要实现浅复制,请在复制的对象上设置一个值,然后返回该值,执行以下操作:

setInputs(prevInputs => {
  const newInputs = Object.assign({}, prevInputs); // Shallow copy
  newInputs[name] = value; // Assign new value
  return newInputs; // Return copied object
});
或者,相当于:

setInputs(prevInputs => Object.assign({}, prevInputs, {[name]: value }));
上述操作之所以有效,是因为
Object.assign
返回新对象(第一个参数)


请记住,这样可以避免对象扩展语法(即ES2018),从而使代码与ES2015兼容。要使代码与ES5(ES2009)兼容,需要做更多的工作。无论哪种方式,为了使您的代码兼容,最好使用自动处理-这样可以使您的源文件保持良好的可读性,同时允许过时的浏览器理解传输的代码。

根据巴别塔本身的说法,spread操作符似乎与浏览器兼容


改用Babel,您就不必担心浏览器的兼容性了。不要为了过时的浏览器而削弱代码的可读性。此外,目标价差为ES2018,而非ES2015。(事实上,既然您使用的是React,那么您的代码不应该被传输吗?)如果您希望
originalObj
与另一个对象相同(
===
),那么唯一的方法就是实际地修改
originalObj
,这是不应该做的(至少在React中)@当然,我使用的是Babel,当我查看传输的代码时,我在源文件中看到了Spread运算符……我认为应该生成一个SyntaxError,或者应该正确传输。生成的输出仅在新浏览器中有效。