使用MobX时,延迟加载属性的当前惯用方法是什么?
我已经在这几天苦苦挣扎了,而且我没有找到任何好的例子,因为严格的模式已成为一件事。我喜欢严格模式的想法,但我开始认为延迟加载与它不一致(访问或观察属性应该触发加载数据的副作用,如果它还没有)。
这是我的问题的症结所在,但看看我如何到这里继续阅读。
我当前设置的基础知识(不发布大量代码):
React Component 1(ListView): componentWillMount
这一切似乎都运作良好。
问题是提案具有client和clientId的属性。 Proposal.clientId是一个加载了提案的字符串。我想等到实际访问客户端告诉商店从服务器获取它(假设它不在商店中)。在这种情况下,ListView恰好显示客户端名称,因此应在Proposal之后不久加载。
我最接近的是在Proposal的构造函数列表中设置了一个自动运行,但其中一部分并没有在我无限的地方做出反应。 (截断到相关部分):
@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;
}
我感觉我正在与系统作战,并且在构造函数中设置autoruns似乎并不理想。有人以合理的方式解决这种模式吗?如果我的设置看起来很疯狂,我愿意接受有关整个事情的建议。
编辑1:为清晰起见,删除了@Mobx。
编辑2: 试图重新评估我的情况,我(再次)找到了优秀的lib 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)。我不介意一些懒惰属性的样板,但我肯定对那里的建议持开放态度。
如果这最终成为了可行的方法,我也将从同一个lib而不是我的可观察请求对象中查看fromPromise。不确定因为我正在跟踪开始时间以检查陈旧性。链接到这里以防其他人没有遇到它:)
答案 0 :(得分:2)
我一直在我的项目中使用不同的方法,并将其解压缩到一个单独的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)
并为您缓存数据。