MobX - 当我在将数据注入 React 组件时可以使用"注入"时,为什么我应该使用"观



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

我的理解是,对于observer,上次渲染中所有访问的可观察量的变化将导致重新渲染,即使可观察量嵌套在数据存储的深处,而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,因为它可以为您提供更多的控制,并且可以防止不必要的重新渲染。如果数据是深度嵌套的,则可以创建一个计算属性,该属性从深层结构获取和准备数据,然后将该属性注入到组件中。

使用一个而不是另一个时是否有其他优点/缺点

我相信你的评估是正确的。为了清楚起见,让我试着改写一下:

@observer跟踪render使用的可观察量,并在其中一个值更改时自动重新渲染组件。

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

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

使用观察者,所有访问的更改 上次渲染中的可观察量将导致重新渲染,即使 可观察嵌套在数据存储的深处

宾果游戏!

虽然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似乎比shouldComponentUpdate更有效。

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

我不一定会走那么远...这完全取决于您如何构建代码。

如果我修改您的原始示例如下:

class Store{
@observable data = {
nestedData: {}
};
constructor() {
this.data.nestedData.deepData = 'my_data';
}
}

。添加deepData实际上不会作为可观察的更改(即重新渲染)进行选取,因为当我们最初将data标记为可观察值时,该属性并不存在。所以这是一个问题。

另一种方法可能是执行以下操作:

class Person {
@observable name = 'John Doe';
}
class Store{
@observable data = null;
constructor() {
this.data = new Person();
}
}

这允许您将可观察值分散到类中 - 因此您可能仍希望将Store注入组件(以访问Store.data但最终任何可观察的更改都来自更新Person

2019+

自 2019 年起,@inject 方法已弃用。有关更多详细信息,请参阅此文章:https://mobx-react.js.org/recipes-inject

最新更新