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

Jak*_*kke 11 typescript reactjs 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...
Run Code Online (Sandbox Code Playgroud)

我的问题是最后一个函数 - 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
Run Code Online (Sandbox Code Playgroud)

我正在寻找最好的做法和陷阱.任何帮助表示赞赏.

*编辑固定代码示例错误

mwe*_*ate 15

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

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

  • 啊哈!那似乎是我遗漏的一块。每次我翻阅文档时,我都会看到一个部分,就好像它是全新的一样。有趣的是,在我编写问题时,我想到了将计算属性粘贴到组件本身中。[题外话] 顺便说一句,我真的很喜欢 MobX(我是从 redux 转换过来的)。我越了解它是如何工作的,我就越喜欢它。感谢所有的辛勤工作! (3认同)

zor*_*404 5

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

你必须结合useMemo()react和computed()mobx:

打字稿

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();
}
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

例子

export default observer(function MyComponent()
{
    const sum = useComputed(() => observableA.myValue + observableB.myValue);
    return <div>{sum}</div>
})
Run Code Online (Sandbox Code Playgroud)

props 应该处于依赖关系中

export default observer(function MyComponent({observableA, observableB})
{
    const sum = useComputed(() => observableA.myValue + observableB.myValue, null, [observableA, observableB]);
    return <div>{sum}</div>
})
Run Code Online (Sandbox Code Playgroud)

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

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