我是否需要在唯一更改的属性上设置setState?

时间:2018-08-18 03:43:42

标签: reactjs

假设我有一个Person类:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

然后我以状态实例化一个Person对象:

export default class SomeComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      cena: new Person('John Cena', 40)
    }
  }

  render() {
    const { name, age } = this.state.cena;
    return (
      <div>
        <p>Name: {name}</p>
        <p>Age: {age}</p>
      </div>
    )
  }
}

假设我们有一个按钮,可将Cena的年龄增加一岁。尽管我们只需要更改年龄,但使用全新的Person对象设置状态是否安全?

this.setState(prevState => ({
  cena: new Person(prevState.cena.name, prevState.cena.age + 1)
}));

我确实使用Chrome的绘画闪光工具对此进行了测试。当我将this.state.cena设置为年龄增长的全新Person时,仅重绘了Age段落,Name段落保持不变。

但是,我还是有点担心。我应该依靠React来进行有效的浅表比较,还是应该只手动更改需要更改的内容?

我什至不知道该如何实现。如果我只尝试setState的年龄,我仍然必须做类似的事情:

this.setState(prevState => ({
  cena: { ...prevState, age: prevState.age + 1 }
}));

与通过其构造函数创建新Person完全相同。要仅“有效”更新年龄,我必须将“人”传播到州的第一层。

constructor() {
  super();
  this.state = {
    ...new Person('John Cena', 40)
  }
}

这很糟糕,因为以后可能需要创建另一个Person。

因此,我将重述我的问题:我应该设置一个全新的对象并依靠React来进行浅层比较吗?

3 个答案:

答案 0 :(得分:1)

  

我应该依靠React来进行有效的浅表比较,还是应该仅手动更改需要更改的内容?

您传递给setState的所有内容都会与当前状态合并。合并之后,如果状态发生了变化,React将重新渲染使用此状态的组件。

这三个示例在功能上都是相同的,您应该使用最容易理解的示例。

通常,您可以依靠它来表现出色。您还可以通过在适当的地方使用PureComponent和/或功能组件来提高性能。

答案 1 :(得分:0)

您的状态将仅存在于组件(SomeComponent)中,除非它通过函数属性发送回。

为什么不采用您最后提出的解决方案,而扩展新的Person实例。 如果看起来很奇怪,请尝试在构造函数之外实例化该类。

示例:

let person = new Person('Name', 40);
this.state = {
  ...this.person,
};

console.log(this.state); // outputs the instance members

let person = new Person('Name', 40);
this.state = {
  person: this.person
};

console.log(this.state.person); // outputs the instance members

如果您的组件状态需要存储多个Person实例,则可以将它们存储在数组中:

let personA = new Person('A', 21);
let personB = new Person('B', 25);

this.state = {
  persons: [personA, personB]
}

要更新此人,treat the state as if it's immutable

const persons = this.state.persons.slice() //copy the array
persons[1].name = 'C' //manipulate Person 'B' instance
this.setState({ persons }) //set the new state

答案 2 :(得分:-1)

通常,我不会创建用于存储状态的类对象。为了简单起见,我将状态设置为对象:

3x3

现在,我可以像这样简单地更改状态:

this.state = {
  cena: {
    name: '',
    age: ''
  }
}