简体   繁体   English

我是变异对象吗?

[英]am I mutating object?

am I mutating state object 我正在改变状态对象吗

state = {
  selectedHero: { id: "", name: "", saying: "" }
}

with this method 用这种方法

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

  this.setState({ selectedHero });
};

should I write something like this? 我应该写这样的东西吗?

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

  this.setState({ selectedHero });
};

Yes and no. 是的,没有。 You're not mutating this.state , but you are mutating an object this.state refers to. 您不是要this.state ,而是要this.state引用的对象。 Which you shouldn't do in React. 在React中不应该这样做。

should I write something like this? 我应该写这样的东西吗?

Almost ; 差不多 ; since that involves updating state based on state (the other properties of selectedHero ), you must use the callback version of setState . 由于这涉及基于状态( selectedHero的其他属性)来更新状态,因此必须使用setState的回调版本 Since that means using properties from the synthetic event after handleChange returns, we'll need to grab them up-front: 由于这意味着在handleChange返回后使用合成事件中的属性,因此我们需要handleChange获取它们:

handleChange = e => {
  const {name, value } = e.target;
  this.setState(prevState => {
    let selectedHero = { ...prevState.selectedHero };
    selectedHero[name] = value;
    return { selectedHero };
  })
};

If you don't use the callback version, things will appear to work much of the time, and fail when you have overlapping state updates to selectedHero (remember that state updates are asynchronous); 如果您不使用回调版本,则大多数情况下似乎会正常工作,并且在对selectedHero进行重叠的状态更新时会失败(请记住状态更新是异步的); one will stomp on the other. 一个会脚另一个。


If you like, you can also condense it by using a computed property name after the property spread: 如果您愿意,还可以通过在属性分布后使用计算的属性名称来压缩它:

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

and even throw in some parameter destructuring: 甚至抛出一些参数解构:

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

(Yes, the destructuring will happen before handleChange returns. It happens before your explicit code in handleChange runs at all.) (是的,解构将在handleChange返回之前发生。它发生在handleChange的显式代码handleChange运行之前。)

Yes, you are mutating the selectedHero object. 是的,您正在变异selectedHero对象。 You should do something like this: 您应该执行以下操作:

handleChange = e => {
  let selectedHero = Object.assign({}, this.state.selectedHero);
  selectedHero[e.target.name] = e.target.value;
  this.setState({ selectedHero });
};

The Object.assign call will create a new object, so that your original selectedHero object is not modified Object.assign调用将创建一个对象,这样就不会修改您原来的selectedHero对象。

Edit: Your edited use of the ES2018 spread syntax works too. 编辑:您对ES2018传播语法的编辑使用也可以使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM