MobX - 当我可以使用 `inject` 将数据注入 React 组件时,为什么我应该使用 `observer`
MobX - Why should I use `observer` when I could use `inject` when injecting data into a React component
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
,因为它可以让您有更多的控制权,并且可以防止不必要的重新渲染。如果数据嵌套很深,你可以创建一个计算的 属性 从深层结构中获取和准备数据,然后将 属性 注入组件。
有没有其他的benefits/drawbacks当一个比另一个使用时
我相信您的评估是正确的。为了清楚起见,让我尝试改写一下:
@observer
跟踪 render
使用了哪些可观察对象,并在这些值之一发生变化时自动重新渲染组件。
我们应该注意 render
使用的 @observable
值可能深深嵌套在给定的 prop
中,根据您的示例:
class Store{
@observable data = {
nestedData: {
// changes to `deepData` would theoretically re-render any observer
deepData: 'my_data'
}
}
}
with observer, a change in all accessed
observables in the last render will cause a re-render, even if the
observable is nested deep in the data store
宾果!
尽管 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 only
re-renders when observables accessed in the injector function change.
宾果!
inject
只会在 prop
本身识别出变化时才会重新渲染。
这实际上是 shouldComponentUpdate() and a deep-comparison of props
-- though observer
seems to be far more efficient 与 shouldComponentUpdate
相同的问题。
In my opinion, it's better to use only inject as it gives you more
control, and can prevent unnecessary re-renders.
我不一定会走那么远...这完全取决于您的代码结构。
如果我这样修改你原来的例子:
class Store{
@observable data = {
nestedData: {}
};
constructor() {
this.data.nestedData.deepData = 'my_data';
}
}
...添加 deepData
实际上不会被视为可观察到的变化(即重新渲染),因为当我们最初标记 [= 时 属性 不存在29=] 作为一个可观察的值。所以这是一个问题。
另一种方法可能是做这样的事情:
class Person {
@observable name = 'John Doe';
}
class Store{
@observable data = null;
constructor() {
this.data = new Person();
}
}
这允许您将可观察值分散到 类 —— 因此您可能仍想将 Store
注入组件(以访问 Store.data
但最终任何可观察到的变化来自更新 Person
.
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
,因为它可以让您有更多的控制权,并且可以防止不必要的重新渲染。如果数据嵌套很深,你可以创建一个计算的 属性 从深层结构中获取和准备数据,然后将 属性 注入组件。
有没有其他的benefits/drawbacks当一个比另一个使用时
我相信您的评估是正确的。为了清楚起见,让我尝试改写一下:
@observer
跟踪 render
使用了哪些可观察对象,并在这些值之一发生变化时自动重新渲染组件。
我们应该注意 render
使用的 @observable
值可能深深嵌套在给定的 prop
中,根据您的示例:
class Store{
@observable data = {
nestedData: {
// changes to `deepData` would theoretically re-render any observer
deepData: 'my_data'
}
}
}
with observer, a change in all accessed observables in the last render will cause a re-render, even if the observable is nested deep in the data store
宾果!
尽管 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 only re-renders when observables accessed in the injector function change.
宾果!
inject
只会在 prop
本身识别出变化时才会重新渲染。
这实际上是 shouldComponentUpdate() and a deep-comparison of props
-- though observer
seems to be far more efficient 与 shouldComponentUpdate
相同的问题。
In my opinion, it's better to use only inject as it gives you more control, and can prevent unnecessary re-renders.
我不一定会走那么远...这完全取决于您的代码结构。
如果我这样修改你原来的例子:
class Store{
@observable data = {
nestedData: {}
};
constructor() {
this.data.nestedData.deepData = 'my_data';
}
}
...添加 deepData
实际上不会被视为可观察到的变化(即重新渲染),因为当我们最初标记 [= 时 属性 不存在29=] 作为一个可观察的值。所以这是一个问题。
另一种方法可能是做这样的事情:
class Person {
@observable name = 'John Doe';
}
class Store{
@observable data = null;
constructor() {
this.data = new Person();
}
}
这允许您将可观察值分散到 类 —— 因此您可能仍想将 Store
注入组件(以访问 Store.data
但最终任何可观察到的变化来自更新 Person
.