我觉得我得到了大部分的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
我正在寻找最佳实践和陷阱。任何帮助表示赞赏。
*编辑固定代码示例错误
答案 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()
包裹您的组件,否则它不会对更改做出反应!