使用 Object.asassigned 替换状态

Replace state using Object.assign

本文关键字:状态 替换 asassigned Object 使用      更新时间:2023-09-26

对于这个状态{ key: bool }的 React 组件,为什么当单击不同的选项时,新状态中没有省略现有的状态键?

https://jsfiddle.net/69z2wepo/35003/

var Hello = React.createClass({
  getInitialState: function() {
    return {};
  },
  render: function() {
    return (
      <div>
        <div onClick={this.handleClick.bind(this, 'foo')}>Foo</div>
        <div onClick={this.handleClick.bind(this, 'bar')}>Bar</div>
        <div onClick={this.handleClick.bind(this, 'baz')}>Baz</div>
        <div>{ 'Foo State: ' + this.state.foo }</div>
        <div>{ 'Bar State: ' + this.state.bar }</div>
        <div>{ 'Baz State: ' + this.state.baz }</div>
      </div>
    );
  },
  handleClick: function(id) {
    this.setState(Object.assign({}, { [id]: !this.state[id] } ));
  }
});
以下是

正在发生的事情:

  1. 单击Foo:状态变为{ foo: true }(预期)
  2. 单击Foo:状态变为{ foo: false }(预期)
  3. 单击Foo:状态变为{ foo: true }(预期)
  4. 单击Bar:状态变为{ foo: true, bar: true }(非预期)

我使用 Object.assign 的目的是清除任何现有状态并将其替换为新的键/布尔对。

有人可以解释为什么在步骤 4 中,{ foo: true }保持状态吗?

如何在不必知道哪个选项以前处于活动状态的情况下清除现有状态?

--

(注意:我在原始帖子之后添加了最后一行,因为知道为什么setState的行为方式而不知道该怎么做并不是很有帮助。我会接受基于原始帖子的答案。请参阅我的答案,了解用未弃用的 API 替换状态的半干净方法)。

setState本身旨在将新状态与现有状态合并(并根据需要更新键)。您永远不会用新对象替换整个状态。

还值得注意的是,在这种情况下无需调用Object.assign。你对setState的呼唤应该只是:

this.setState({ [id]: !this.state[id] });

如果您希望自己处理合并,则需要改用replaceState(这会给您所需的行为):

this.replaceState(Object.assign({}, { [id]: !this.state[id] });

setState合并到键中,而不是完全覆盖状态。

replaceState已被弃用(如果您尝试使用它,请参阅此处,此处,此处,此处和控制台),正如Justin/Andy所解释的那样,setState将始终合并,永远不会替换。

我能想到的清除现有状态的最干净的方法是将初始状态设置为 { active: {} },然后根据需要使用此单行代码切换或替换:

this.setState({ active: (this.state.active[id]) ? {} : { [id]: true } });