开发者问题收集

如何在 React 中更新嵌套状态属性

2017-03-27
494545

我尝试使用如下嵌套属性来组织我的状态:

this.state = {
   someProperty: {
      flag:true
   }
}

但是像这样更新状态

this.setState({ someProperty.flag: false });

不起作用。如何正确完成此操作?

3个回答

为了对嵌套对象进行 setState ,您可以按照下面的方法,因为我认为 setState 不处理嵌套更新。

var someProperty = {...this.state.someProperty}
someProperty.flag = true;
this.setState({someProperty})

这个想法是创建一个虚拟对象,对其执行操作,然后用更新后的对象替换组件的状态

现在,扩展运算符仅创建对象的一个​​级别嵌套副本。如果您的状态是高度嵌套的,例如:

this.state = {
   someProperty: {
      someOtherProperty: {
          anotherProperty: {
             flag: true
          }
          ..
      }
      ...
   }
   ...
}

您可以在每个级别使用扩展运算符设置状态,例如

this.setState(prevState => ({
    ...prevState,
    someProperty: {
        ...prevState.someProperty,
        someOtherProperty: {
            ...prevState.someProperty.someOtherProperty, 
            anotherProperty: {
               ...prevState.someProperty.someOtherProperty.anotherProperty,
               flag: false
            }
        }
    }
}))

但是,随着状态变得越来越嵌套,上述语法变得越来越丑陋,因此我建议您使用 immutability-helper 包来更新状态。

有关如何使用 immutability-helper 更新状态,请参阅 此答案

Shubham Khatri
2017-03-27

用一行写

this.setState({ someProperty: { ...this.state.someProperty, flag: false} });
Yoseph
2017-08-09

有时直接的答案并不是最好的答案 :)

简短版本:

此代码

this.state = {
    someProperty: {
        flag: true
    }
}

应简化为类似

this.state = {
    somePropertyFlag: true
}

长版本:

目前 您不应该想在 React 中使用嵌套状态 。因为 React 不适用于处理嵌套状态,并且此处提出的所有解决方案看起来都是黑客攻击。他们不使用框架,而是与之抗争。他们建议编写不太清晰的代码,以便对某些属性进行分组的可疑目的。因此,它们作为挑战的答案非常有趣,但实际上毫无用处。

让我们想象以下状态:

{
    parent: {
        child1: 'value 1',
        child2: 'value 2',
        ...
        child100: 'value 100'
    }
}

如果您仅更改 child1 的值,会发生什么? React 不会重新渲染视图,因为它使用浅比较,它会发现 parent 属性没有改变。顺便说一句,直接改变状态对象通常被认为是一种不好的做法。

因此,您需要重新创建整个 parent 对象。但在这种情况下,我们会遇到另一个问题。React 会认为所有子项都已更改其值,并将重新渲染所有子项。当然,这对性能不利。

仍然可以通过在 shouldComponentUpdate() 中编写一些复杂的逻辑来解决该问题,但我更愿意在这里停下来并使用简短版本的简单解决方案。

Konstantin Smolyanin
2018-07-02