gpt4 book ai didi

javascript - 使用 mobx 进行延迟加载的惯用方法

转载 作者:行者123 更新时间:2023-11-29 21:16:06 27 4
gpt4 key购买 nike

当前使用 MobX 时延迟加载属性的惯用方法是什么?

我已经为此苦苦挣扎了几天,自从严格模式成为现实以来,我还没有找到任何好的例子。我喜欢严格模式的想法,但我开始认为延迟加载与它不一致(访问或观察属性应该触发加载数据的副作用,如果它不存在的话)。

这是我问题的症结所在,但要了解我是如何走到这里的,请继续阅读。

我当前设置的基础知识(无需发布大量代码):

React 组件 1( ListView ):componentWillMount

  1. componentWillMount & componentWillReceiveProps - 组件从路由参数 (react-router) 获取过滤器值,将其保存为 ListView 上的可观察对象,并告诉商店根据它获取“建议”
  2. Store.fetchProposals 检查是否已经发出该请求(请求存储在 ObservableMap 中,通过序列化过滤器对象作为键,因此两个相同的过滤器将返回相同的响应对象)。它会在需要时发出请求,并返回可观察的响应对象,该对象包含有关请求是完成还是有错误的信息。
    1. ListView 将可观察的响应对象保存为属性,以便它可以显示加载或错误指示器。
    2. ListView 有一个计算属性,它调用 Store.getProposals 使用与获取相同的过滤器对象
    3. Store.getProposals 是一个转换器,它接受一个过滤器对象,从 ObservableMap(proposal.id 上的键)获取所有建议,使用过滤器对象过滤列表并返回一个 Proposal[](如果没有匹配过滤器则为空,包括如果尚未加载任何提案)

这一切似乎都运作良好。

问题是提案具有 client 和 clientId 的属性。 Proposal.clientId 是与提案一起加载的字符串。我想等到实际访问客户端时告诉商店从服务器获取它(假设它不在商店中)。在这种情况下,ListView 恰好显示了客户端名称,因此应该在 Proposal 之后不久加载它。

我最接近的是在提案的构造函数列表中设置一个自动运行,但它的一部分并没有在我打算的地方使用react。 ( chop 为相关部分):

@observable private clientId: string = '';
@observable private clientFilter: IClientFilter = null;
@observable client: Client = null;

constructor(sourceJson?: any) {
super(sourceJson);
if (sourceJson) {
this.mapFromJson(sourceJson);
}
//this one works. I'm turning the clientId string into an object for the getClients transformer
autorun(() => { runInAction(() => { this.clientFilter = { id: this.clientId }; }) });
autorun(() => {
runInAction(() => {
if (this.clientId && this.clientFilter) {
const clients = DataStore.getClients(this.clientFilter);
const response = DataStore.fetchClients(this.clientFilter);
if (response.finishedTime !== null && !response.hasErrors) {
this.client = clients[0] || null;
console.log('This is never called, but I should see a client here: %o', DataStore.getClients(this.clientFilter));
}
}
})
});
}

响应对象是可观察的:

export class QueryRequest<T extends PersistentItem | Enum> {
@observable startTime: Date = new Date();
@observable finishedTime: Date = null;
@observable errors: (string | Error)[] = [];
@observable items: T[] = [];
@computed get hasErrors() { return this.errors.length > 0; }
@observable usedCache: boolean = false;
}

我感觉我在与系统作斗争,无论如何在构造函数中设置自动运行似乎并不理想。有人以合理的方式解决这个模式吗?如果我的设置看起来很疯狂,我愿意接受关于整个事情的建议。


编辑 1:为清楚起见删除了@Mobx。


编辑 2:试图重新评估我的情况,我(再次)找到了优秀的库 mobx-utils ,它有一个 lazyObservable可能适合我需要的功能。目前它看起来像这样:

client = lazyObservable((sink) => {
autorun('lazy fetching client', () => {
if (this.clientFilter && this.clientFilter.id) {
const request = DataStore.fetchClients(this.clientFilter);
if (request.finishedTime !== null && !request.hasErrors) {
sink(request.items[0]);
}
}
})
}, null);

这是有效的!

我想我需要那里的自动运行来根据这个对象的 clientId/clientFilter 属性进行更新(如果这个对象稍后被分配给一个新的客户端,我希望更新 lazyObservable)。我不介意为惰性属性提供一些样板,但我绝对乐于接受那里的建议。

如果这最终是要走的路,我也会看看 fromPromise来自同一个库而不是我的可观察请求对象。不确定,因为我正在跟踪开始时间以检查是否过时。链接在这里以防其他人没有遇到它:)

最佳答案

我一直在我的项目中使用不同的方法,并将其提取到一个单独的 npm 包中:https://github.com/mdebbar/mobx-cache

这是一个简单的例子:

首先,我们需要一个 React 组件来显示客户端信息:

@observer
class ClientView extends React.Component {
render() {
const entry = clientCache.get(this.props.clientId)

if (entry.status !== 'success') {
// Return some kind of loading indicator here.
return <div>Still loading client...</div>
}

const clientInfo = entry.value
// Now you can render your UI based on clientInfo.
return (
<div>
<h2>{clientInfo.name}</h2>
</div>
)
}
}

然后,我们需要设置clientCache:

import MobxCache from "mobx-cache";

function fetchClient(id) {
// Use any fetching mechanism you like. Just make sure to return a promise.
}

const clientCache = new MobxCache(fetchClient)

这就是您需要做的全部。 MobxCache 会在需要时自动调用 fetchClient(id) 并为您缓存数据。

关于javascript - 使用 mobx 进行延迟加载的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39369506/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com