当setState与类的对象实例时,会发生什么反应

时间:2016-07-20 09:21:59

标签: class reactjs instance setstate

我有fiddle

let m = new Mine();
this.setState(m, () => {
    console.log('1:', m instanceof Mine, m.x, m.meth);
    // => 1: true 123 function meth() {}
    console.log('2:', this.state instanceof Mine, this.state.x, this.state.meth);
    // => 2: false 123 undefined
});

如您所见,我创建了Mine类的实例,然后在具有该实例的react组件中设置状态。

我希望this.state完全包含该实例,但是当构造函数中设置的实例属性可用时,我无法访问该实例上的任何类方法。

小提琴中的测试显示this.state不是Mine类的实例。

是否有人了解发生了什么或是否是这种意外行为?

3 个答案:

答案 0 :(得分:2)

经过更多调查后,我发现了发生这种情况的原因。

react的函数_processPendingState使用Object.assign来设置新状态,因为目标对象是一个新对象(不同于传递给setState的对象),新状态失去了作为“我的实例”的质量“上课。

因为Object.assign只将自己的可枚举属性从源复制到目标,所以新状态也不会有类方法。

如果在小提琴中我们替换了那条线......

let m = {x: 123};
Object.defineProperty(m, 'meth', {
    enumerable: false,
    get() { return function() {}; }
});

...与

@mixin vendor($attribute, $value, $vendors: (moz, ms, webkit)) {
    @each $vendor in $vendors {
        -#{$vendor -$attribute}: $value;
    }
    #{$attribute}: $value;
}

我们在结果状态下仍然没有“meth”属性。即使“m”拥有“meth”属性,它也是不可枚举的。

答案 1 :(得分:2)

最佳解决方案是将方法表示为箭头函数:

class Blah {
  constructor() {
    // no definition here for surfacedMethod!
  }

  surfacedMethod = () => {
    // do something here
  }

}

然后,您可以在setState中设置此类的实例,并使用它们的方法,就像它们是在实例上设置的属性一样。

// other component innards
this.setState(state => ({blah: new Blah()}))

// later
this.state.blah.surfacedMethod();  // this will now work

答案 2 :(得分:0)

在这种情况下使用replaceState,它应该有用。