什么时候在 mobx 中使用 computed/observables
When to use computed/observables in mobx
我觉得我了解了大部分的 mobx,但我想澄清一些事情。我有一个带有一些可观察对象的商店,其核心是一个对象数组(打字稿):
class ClientStore {
constructor() {
this.loadClients();
}
@observable private _clients: IClient[] = [];
@computed get clients() {
return this._clients;
}
@observable isFetching: boolean = false;
@observable sortField: 'title' | 'modified' = 'modified';
@observable sortDescending: boolean = true;
getClientByUrlName(urlName: string): IClient {
return this._clients.find(c => c.urlName === urlName);
}
etc...
我的问题是最后一个函数 - getClientByUrlName。由于这是从可观察对象中发现的,因此使用该函数的任何 @observer 反应组件都会正确重新呈现。这是惯用的 mobx 吗?感觉应该是一个计算值。我应该在要使用它的组件中创建一个计算值吗?
//import singletone ClientStore
class ClientDetailsView extends React.Component<{params:{urlName:string}}, void> {
@computed get client() {
return ClientSotre.clients.find(c => c.urlName === this.props.params.urlName);
}
...rest of react component
我正在寻找最佳实践和陷阱。感谢任何帮助。
*编辑修复代码示例错误
原则上 @computed
是一个简单的指令,它告诉 MobX:"this value could be cached until any of the observables that is used changes"。所以实际上它们总是可以被排除在外,这只是意味着您的应用程序将重新计算更多,但不会改变结果。
因此,如果您缺少 @computed
原则上在大多数情况下都不是问题的功能。如果是,您可以使用 createTransformer
它接受一个参数函数并构建一个(自清理)计算值的记忆缓存。但它有点复杂,所以实际上你在 ClientDetailsView
中引入计算 属性 的解决方案更好。我确实会建议这样做,只要你有一个很好的地方来放置计算出的 属性(在这种情况下需要它的组件)
任何想知道如何在 Functional Components.
中使用 Computed 的人
你必须结合来自 react 的 useMemo()
和来自 mobx 的 computed()
:
TypeScript
import {useMemo} from 'react';
import {computed, IComputedValueOptions} from 'mobx';
// changes to "options" argument are ignored
export default function useComputed<T>(func: () => T, options?: IComputedValueOptions<T>, deps?: DependencyList)
{
return useMemo(() => computed(func, options), deps ?? []).get();
}
JavaScript
import {useMemo} from 'react';
import {computed} from 'mobx';
// changes to "options" argument are ignored
export default function useComputed(func, options)
{
return useMemo(() => computed(func, options), deps ?? []).get();
}
例子
export default observer(function MyComponent()
{
const sum = useComputed(() => observableA.myValue + observableB.myValue);
return <div>{sum}</div>
})
道具应该依赖
export default observer(function MyComponent({observableA, observableB})
{
const sum = useComputed(() => observableA.myValue + observableB.myValue, null, [observableA, observableB]);
return <div>{sum}</div>
})
如果您不将道具放在 deps 中,那么 computed()
将继续使用旧道具并且永远不会更新。
不要忘记用 observer()
包装您的组件,否则它不会对更改做出反应!
我觉得我了解了大部分的 mobx,但我想澄清一些事情。我有一个带有一些可观察对象的商店,其核心是一个对象数组(打字稿):
class ClientStore {
constructor() {
this.loadClients();
}
@observable private _clients: IClient[] = [];
@computed get clients() {
return this._clients;
}
@observable isFetching: boolean = false;
@observable sortField: 'title' | 'modified' = 'modified';
@observable sortDescending: boolean = true;
getClientByUrlName(urlName: string): IClient {
return this._clients.find(c => c.urlName === urlName);
}
etc...
我的问题是最后一个函数 - getClientByUrlName。由于这是从可观察对象中发现的,因此使用该函数的任何 @observer 反应组件都会正确重新呈现。这是惯用的 mobx 吗?感觉应该是一个计算值。我应该在要使用它的组件中创建一个计算值吗?
//import singletone ClientStore
class ClientDetailsView extends React.Component<{params:{urlName:string}}, void> {
@computed get client() {
return ClientSotre.clients.find(c => c.urlName === this.props.params.urlName);
}
...rest of react component
我正在寻找最佳实践和陷阱。感谢任何帮助。
*编辑修复代码示例错误
原则上 @computed
是一个简单的指令,它告诉 MobX:"this value could be cached until any of the observables that is used changes"。所以实际上它们总是可以被排除在外,这只是意味着您的应用程序将重新计算更多,但不会改变结果。
因此,如果您缺少 @computed
原则上在大多数情况下都不是问题的功能。如果是,您可以使用 createTransformer
它接受一个参数函数并构建一个(自清理)计算值的记忆缓存。但它有点复杂,所以实际上你在 ClientDetailsView
中引入计算 属性 的解决方案更好。我确实会建议这样做,只要你有一个很好的地方来放置计算出的 属性(在这种情况下需要它的组件)
任何想知道如何在 Functional Components.
中使用 Computed 的人你必须结合来自 react 的 useMemo()
和来自 mobx 的 computed()
:
TypeScript
import {useMemo} from 'react';
import {computed, IComputedValueOptions} from 'mobx';
// changes to "options" argument are ignored
export default function useComputed<T>(func: () => T, options?: IComputedValueOptions<T>, deps?: DependencyList)
{
return useMemo(() => computed(func, options), deps ?? []).get();
}
JavaScript
import {useMemo} from 'react';
import {computed} from 'mobx';
// changes to "options" argument are ignored
export default function useComputed(func, options)
{
return useMemo(() => computed(func, options), deps ?? []).get();
}
例子
export default observer(function MyComponent()
{
const sum = useComputed(() => observableA.myValue + observableB.myValue);
return <div>{sum}</div>
})
道具应该依赖
export default observer(function MyComponent({observableA, observableB})
{
const sum = useComputed(() => observableA.myValue + observableB.myValue, null, [observableA, observableB]);
return <div>{sum}</div>
})
如果您不将道具放在 deps 中,那么 computed()
将继续使用旧道具并且永远不会更新。
不要忘记用 observer()
包装您的组件,否则它不会对更改做出反应!