Javascript 我是变异对象吗?

Javascript 我是变异对象吗?,javascript,reactjs,Javascript,Reactjs,我是变异状态对象吗 state = { selectedHero: { id: "", name: "", saying: "" } } 用这种方法 handleChange = e => { let selectedHero = this.state.selectedHero; selectedHero[e.target.name] = e.target.value; this.setState({ selectedHero }); }; 我应该这样写吗 handl

我是变异状态对象吗

state = {
  selectedHero: { id: "", name: "", saying: "" }
}
用这种方法

handleChange = e => {
  let selectedHero = this.state.selectedHero;
  selectedHero[e.target.name] = e.target.value;

  this.setState({ selectedHero });
};
我应该这样写吗

handleChange = e => {
  let selectedHero = { ...this.state.selectedHero };
  selectedHero[e.target.name] = e.target.value;

  this.setState({ selectedHero });
};
是的,您正在变异selectedHero对象。你应该这样做:

handleChange = e => {
  let selectedHero = Object.assign({}, this.state.selectedHero);
  selectedHero[e.target.name] = e.target.value;
  this.setState({ selectedHero });
};
Object.assign调用将创建一个新对象,以便不会修改原始selectedHero对象

编辑:您对作品的编辑使用。

是的,您正在修改selectedHero对象。你应该这样做:

handleChange = e => {
  let selectedHero = Object.assign({}, this.state.selectedHero);
  selectedHero[e.target.name] = e.target.value;
  this.setState({ selectedHero });
};
Object.assign调用将创建一个新对象,以便不会修改原始selectedHero对象


编辑:您对作品的编辑使用。

是和否。您不是在修改this.state,而是在修改this.state引用的对象。这是你不应该做的

我应该这样写吗

几乎;因为这涉及到基于selectedHero的其他属性的状态更新状态,所以您可以。因为这意味着在handleChange返回后使用合成事件中的属性,所以我们需要提前获取它们:

handleChange = e => {
  const {name, value } = e.target;
  this.setState(prevState => {
    let selectedHero = { ...prevState.selectedHero };
    selectedHero[name] = value;
    return { selectedHero };
  })
};
如果您不使用回调版本,很多时候事情都会正常工作,当您选择了重叠的状态更新时就会失败。请记住,状态更新是异步的;一个会踩另一个

如果愿意,还可以在特性排列后使用计算出的特性名称对其进行压缩:

handleChange = e => {
  const {name, value} = e.target;
  this.setState(prevState => ({selectedHero: {...prevState.selectedHero, [name]: value}}));
};
甚至还有一些参数分解:

handleChange = ({target: {name, value}}) => {
  this.setState(prevState => ({selectedHero: {...prevState.selectedHero, [name]: value}}));
};

是的,解构将在handleChange返回之前发生。它发生在handleChange中的显式代码运行之前。

是和否。您不是在修改this.state,而是在修改this.state引用的对象。这是你不应该做的

我应该这样写吗

几乎;因为这涉及到基于selectedHero的其他属性的状态更新状态,所以您可以。因为这意味着在handleChange返回后使用合成事件中的属性,所以我们需要提前获取它们:

handleChange = e => {
  const {name, value } = e.target;
  this.setState(prevState => {
    let selectedHero = { ...prevState.selectedHero };
    selectedHero[name] = value;
    return { selectedHero };
  })
};
如果您不使用回调版本,很多时候事情都会正常工作,当您选择了重叠的状态更新时就会失败。请记住,状态更新是异步的;一个会踩另一个

如果愿意,还可以在特性排列后使用计算出的特性名称对其进行压缩:

handleChange = e => {
  const {name, value} = e.target;
  this.setState(prevState => ({selectedHero: {...prevState.selectedHero, [name]: value}}));
};
甚至还有一些参数分解:

handleChange = ({target: {name, value}}) => {
  this.setState(prevState => ({selectedHero: {...prevState.selectedHero, [name]: value}}));
};


是的,解构将在handleChange返回之前发生。它发生在handleChange中的显式代码运行之前。

console.log..正如AnilRedshift所说,是的,您给出的扩展语法示例可以很好地工作。对于更简洁的方法,您也可以使用这样的一行代码编写:this.setState{…this.state.selectedHero,name:e.target.value}。这将同时覆盖新对象上的名称值并避免变异。@TPHughes-否,Anil的版本无法使用回调,这是必需的。还有,名字!=[e.target.name]:-啊,是的,你完全正确。我把钥匙的名字误读成了名字。我在手机上写着:-/。你是什么意思,为什么需要回拨?@TPHughes-请参阅下面我的答案以及其中的链接:-log..正如AnilRedshift所说,是的,您给出的扩展语法示例可以很好地工作。对于更简洁的方法,您也可以使用这样的一行代码编写:this.setState{…this.state.selectedHero,name:e.target.value}。这将同时覆盖新对象上的名称值并避免变异。@TPHughes-否,Anil的版本无法使用回调,这是必需的。还有,名字!=[e.target.name]:-啊,是的,你完全正确。我把钥匙的名字误读成了名字。我在手机上写着:-/。你是什么意思,为什么需要回拨?@TPHughes-请参阅下面我的答案以及其中的链接:-由于这涉及到根据正在复制的selectedHero的现有状态和其他属性设置状态,因此您必须使用setState的回调版本:不这样做在大多数情况下都会起作用,并且在合并/批处理状态更新时失败。由于这涉及到根据现有状态设置状态以及要复制的selectedHero的其他属性,因此必须使用setState的回调版本:不这样做似乎在大多数情况下都有效,合并/批处理状态更新时失败。我收到警告:出于性能原因,此合成事件被重用。如果您看到了这一点,那么您正在访问已发布/已取消的合成事件的属性目标。这被设置为null。如果必须保留原始合成事件,请使用事件。persist@d_oram-哦,哇,我不知道。不过,这是一条清晰的错误消息。我们必须在本地获取名称和值,然后使用它们。你可能知道怎么做,但我还是会更新答案的。@d_oram-Done.完美,谢谢。你能在第一次返回{selectedHero}后加上右括号}吗example@d_oram-哎呀!第二个和第三个也丢失了一个-我得到警告:这个合成事件是重复使用的
出于性能原因。如果您看到了这一点,那么您正在访问已发布/已取消的合成事件的属性目标。这被设置为null。如果必须保留原始合成事件,请使用事件。persist@d_oram-哦,哇,我不知道。不过,这是一条清晰的错误消息。我们必须在本地获取名称和值,然后使用它们。你可能知道怎么做,但我还是会更新答案的。@d_oram-Done.完美,谢谢。你能在第一次返回{selectedHero}后加上右括号}吗example@d_oram-哎呀!第二个和第三个也丢失了一个-