Mat*_*nik 5 javascript reactjs react-native mobx mobx-react
MobX文档建议我应该observer在所有组件上使用。但是,通过使用注入,我可以更精细地控制哪些数据导致组件的重新呈现。
我的理解是,有了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 { }
Run Code Online (Sandbox Code Playgroud)
有人可以确认我对此的理解吗?
我认为,最好只使用inject它,因为它可以给您更多的控制权,并且可以防止不必要的重新渲染。如果数据是深度嵌套的,则可以创建一个计算属性,该属性从深度结构获取并准备数据,然后将该属性注入到组件中。
在彼此之间使用时是否还有其他好处/缺点?
我相信你的评估是正确的。为了清楚起见,让我尝试重新表述:
@observer跟踪哪些 observable 被使用,render并在这些值之一发生变化时自动重新渲染组件。
我们应该注意,根据您的示例,@observableby 使用的值render可能深深嵌套在给定的 中prop:
class Store{
@observable data = {
nestedData: {
// changes to `deepData` would theoretically re-render any observer
deepData: 'my_data'
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用观察者,最后一次渲染中所有访问的 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>
);
Run Code Online (Sandbox Code Playgroud)
仅当注入器函数中访问的可观察对象发生变化时才重新渲染。
答对了!
inject如果prop本身已经识别出更改,则只会产生重新渲染。
这实际上是同一个问题shouldComponentUpdate()和深比较props-虽然observer似乎是更为有效的比shouldComponentUpdate。
在我看来,最好只使用注入,因为它给你更多的控制,并且可以防止不必要的重新渲染。
我不一定会走那么远……这完全取决于您的代码结构。
如果我这样修改你的原始示例:
class Store{
@observable data = {
nestedData: {}
};
constructor() {
this.data.nestedData.deepData = 'my_data';
}
}
Run Code Online (Sandbox Code Playgroud)
...添加的deepData实际上不会作为可观察的更改(即重新渲染)被拾取,因为当我们最初标记data为可观察值时,该属性不存在。所以这是一个问题。
一种不同的方法可能是做这样的事情:
class Person {
@observable name = 'John Doe';
}
class Store{
@observable data = null;
constructor() {
this.data = new Person();
}
}
Run Code Online (Sandbox Code Playgroud)
这允许您将 observable 值分散到各个类中——因此您可能仍然希望注入Store到一个组件中(以访问Store.data但最终任何可观察的更改都来自更新Person.