MobX - 当我将数据注入React组件时,为什么我可以使用`observe`来使用`observer`

时间:2018-01-25 06:48:11

标签: javascript reactjs react-native mobx mobx-react

MobX文档建议我应该在所有组件上使用observer。但是,通过使用注入,我可以更精细地控制哪些数据导致重新呈现我的组件。

我的理解是,对于observer,即使observable嵌套在数据存储的深处,最后渲染中所有被访问的observable的更改也会导致重新渲染,而inject只有在进样器功能中访问的可观察量发生变化时才重新渲染。

例如:

class Store{
  @observable data = {
    nestedData: {
      deepData: 'my_data'
    }
  }
}

const store = new Store();

... Assume the store is injected using <Provider /> component

// This will cause re-render when the data object changes
// for example: store.data = { new_data: 'new_data' }
@inject(stores => {
  return { data: stores.dataStore.data }; 
})
class MyComponent extends Component {  }

// This will re-render on change of the data object, but also
// on change of nestedData and deepData properties
@inject(stores => {
  return { data: stores.dataStore.data }; 
})
@observer
class MyComponent extends Component {  }

有人可以证实我对此的理解吗?

在我看来,最好只使用inject,因为它可以提供更多控制,并且可以防止不必要的重新渲染。如果数据是深度嵌套的,您可以创建一个计算属性,从深层结构中获取并准备数据,然后将该属性注入组件中。

使用其他优点/缺点时是否存在其他优点/缺点

1 个答案:

答案 0 :(得分:4)

我相信你的评估是正确的。让我试着澄清一下:

@observer跟踪render使用哪些可观察对象,并在其中一个值发生变化时自动重新呈现该组件。

我们应该注意@observable使用的render值可能会根据您的示例深深嵌套在给定的prop中:

class Store{
  @observable data = {
    nestedData: {
      // changes to `deepData` would theoretically re-render any observer
      deepData: 'my_data' 
    }
  }
}
  

与观察者,所有访问的变化   最后渲染中的observable将导致重新渲染,即使是   observable嵌套在数据存储的深处

<强>宾果!

虽然observable有一个怪癖,但你马上就会看到......

另一方面,您拥有@inject,这可以使组件(通过props)由Provider定义的特定数据结构。

例如:

@inject('title')
class MyComponent extends React.Component {
    render() {
        return (<div>{this.props.title}</div>);
    }
}

const Container = () => (
    <Provider title="This value is passed as a prop using `inject`">
        <MyComponent />
    </Provider>
);
  

仅注射   当在喷油器功能中访问的可观察量发生变化时重新渲染。

<强>宾果!

如果inject本身已识别出更改,

prop将仅生成重新渲染。

这与shouldComponentUpdate()实际上是同一个问题,props的深度比较 - 尽管observer似乎是far more efficient而不是shouldComponentUpdate。< / p>

  

在我看来,只使用注射会更好,因为它会给你更多   控制,并可以防止不必要的重新渲染。

我不一定会那么远......这一切都取决于你的代码结构如何。

如果我修改原始示例:

class Store{
    @observable data = {
        nestedData: {}
    };

    constructor() {
        this.data.nestedData.deepData = 'my_data';
    }
}

... deepData的添加实际上不会被视为可观察的变化(即重新渲染),因为当我们最初标记{{1}时,该属性并不存在作为可观察的值。这就是一个问题。

另一种方法可能是做这样的事情:

data

这允许您跨类传播可观察值 - 因此您可能仍希望将class Person { @observable name = 'John Doe'; } class Store{ @observable data = null; constructor() { this.data = new Person(); } } 注入组件(以访问Store,但最终任何可观察到的更改都来自更新{{1 }}