15

我觉得我得到了 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。由于这是从 observable 中发现的,因此任何使用该函数的 @observer react 组件都会正确重新渲染。这是惯用的 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

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

*编辑固定代码示例错误

4

2 回答 2

19

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

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

于 2016-06-28T14:51:52.937 回答
2

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

你必须结合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();
}

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()否则它不会对更改做出反应!

于 2021-02-24T14:53:58.720 回答