在保留类类型的同时对嵌套对象反应setState

时间:2018-11-01 12:18:47

标签: javascript reactjs

从这个问题开始React Set State For Nested Object

更新嵌套状态的方法是分解对象,然后像下面这样重建它:

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

但是,这对我来说是个问题,因为它不会保留组件类(下面有更多详细信息)。我的目标是使我的国家结构如下:

this.state = {
    addressComponent: {
        street: '',
        number: '',
        country: ''
    },
    weather: {
        /* some other state*/
    }
}

为了使我的生活更轻松,我创建了一个简单的地址类,该地址类可以为我构建对象并具有其他一些实用功能,例如验证。

class AddressComponent {
    constructor(street, number, country) {
        this.street = street;
        this.number = number;
        this.country = country;
    }

    validate() {
        if (this.street && this.number, this.country) {
            return true;
        }
        return false;
    }
}

这允许我做的是将状态的初始化更改为:

this.state = {
    addressComponent : new AddressComponent(),
    weather: new WeatherComponent();
 }

 this will allow my view component to perform nice things like

if (this.state.addressComponent.validate()) {
    // send this state to parent container
}

这种方法的问题是,如果我想突变单个信息(例如国家/地区)并使用上述堆栈溢出方法,例如:

this.setState({addressComponent: {...addressComponent, country: 'bluh'}})

这样做将意味着解析的addressComponent不再是AddressComponent类的一部分,因此没有validate()函数

要解决这个问题,我每次都会重新创建一个新的AddressComponent类,例如:

this.setState({addressComponent: new AddressComponent(this.state.street, this.state.number, 'bluh');

但这似乎很奇怪。

我做错了吗?有没有更好的方法?这样的类与react一起使用是否可以接受?

3 个答案:

答案 0 :(得分:1)

我认为您所说的关于每次在状态下更新类时都要重新实例化的说法是确保此时调用validate()方法的最干净的方法。如果是我,我可能会这样写:

const { addressComponent } = this.state;
this.setState({ addressComponent: new AddressComponent(addressComponent.street, addressComponent.number, 'bluh') });

答案 1 :(得分:1)

不希望在React状态下使用除普通对象之外的任何东西,以避免类似这种情况。使用类实例还将使状态的序列化和反序列化变得更加复杂。

AddressComponent的存在是没有道理的,它不能从成为一个类中受益。

相同的代码可以用普通对象重写为功能:

const validateAddress = address => !!(street && address.number && address.country);
...

if (validateAddress(this.state.address)) {
    // send this state to parent container
}

答案 2 :(得分:0)

您可以创建一个可重用的函数来更新这样的复杂状态。

updateState = (option, value) => {
  this.setState(prevState => ({
    addressComponent: {
      ...prevState.addressComponent,
      [option]: value
    }
  })
}