何时在mobx中使用计算/可观察量

时间:2016-06-28 13:10:40

标签: reactjs typescript mobx

我觉得我得到了大部分的mobx,但我想澄清一些事情。我有一个带有一些observable的商店,其核心是一个对象数组(typescript):

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

我正在寻找最佳实践和陷阱。任何帮助表示赞赏。

*编辑固定代码示例错误

2 个答案:

答案 0 :(得分:14)

原则上@computed是一个简单的指令,告诉MobX:“此值可以缓存,直到使用的任何可观察对象发生变化”。所以实际上它们总是被排除在外,这只会意味着你的应用会重新计算更多,但它不会改变结果。

因此,如果您在函数上缺少@computed,那么在大多数情况下原则上这不是问题。如果是,则可以使用createTransformer,它采用单参数函数并构建计算值的(自清洁)memoization缓存。但它涉及的更多,所以实际上你在ClientDetailsView中引入计算属性的解决方案更好。我确实建议你这样做,只要你有一个放置计算属性的好地方(在这种情况下需要它的组件)

答案 1 :(得分:1)

对于想知道如何在功能组件中使用计算的人。

你必须将来自 react 的 useMemo() 和来自 mobx 的 computed() 结合起来:

打字稿

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>
})

如果你不把 props 放在 deps 中,那么 computed() 将继续使用旧的 props 并且它永远不会更新。

不要忘记用 observer() 包裹您的组件,否则它不会对更改做出反应!