在加载查询时从中继存储加载数据
Load data from relay store while the query is loading
我有一个公共的 Header
和 Footer
显示它可能已经在中继存储中的数据和主 PageComponent
期望来自“查询”的数据,但是我不想向用户显示完整的加载屏幕,我想在中间显示页眉、页脚和加载屏幕或内容。
因此,如您所知,如果我将所有内容都包装在 QueryRenderer
中,我将有两个选择:查询正在“加载”或数据可用:
<QueryRenderer
{...usualProps}
render={({ error, props }) => {
<div className="app-wrapper">
{ props || error ? <PageComponent {...props} error={error} /> : <div>Loading...</div>}
</div>
}}
/>
假设我有一种方法可以手动从商店中检索数据(因为我们没有从商店中进行部分渲染之类的东西)并且我可以将该信息传递给公共 Header
和 Footer
加载主查询时:
<QueryRenderer
{...usualProps}
render={({ error, props }) => {
<div className="app-wrapper">
<Header {...storeProps} {...props} />
{ props || error ? <PageComponent {...props} error={error} /> : <div>Loading...</div>}
<Footer {...storeProps} {...props} />
</div>
}}
/>
我发现既然有了环境,我可以做这样的事情来获取商店的信息:
const storeProps = relayEnvironment.getStore().lookup({
dataID: 'client:root',
node: query().fragment, // special query with only the information I need for the `Header`
variables: {}
});
但是我遇到了一些问题:
- QueryRenderer 在卸载时处理数据:cry:(虽然我从中读取的信息也应该由查询检索,但从存储中读取更像是查询时的后备 returns)
- 语法看起来很老套
- 我必须创建一个查询并编译它(无论如何我都可以忍受)
可能我以错误的方式解决了这个问题,也许有人做了类似的事情,可以给我一些建议。
(如果没有任何效果,我的计划 B 是使用 getDerivedStateFromProp
将查询信息发送到自定义上下文并将其保存在那里以避免存储 GC 问题,例如)。
TL:DR: 我想在查询完成加载时从存储中加载数据,然后使用查询返回的数据。
有什么想法吗?如果有什么不清楚的地方,请告诉我
用 relayEnvironment
读取商店听起来不是一个好的解决方案。
如果你为 Header
放一个 QueryRenderer
,为 Footer
放另一个,你会怎么想?所以每个人都会获取自己的数据,与页面内容分开。这有意义吗?
希望对您有所帮助:)
Relay 有 Observables 和 Cache 可以结合使用来实现这个。
您可以从 'relay-runtime';
导入 { QueryResponseCache }
然后像这样使用它:
const cache = new QueryResponseCache({
size: CACHE_SIZE, // Number of responses to cache
ttl: CACHE_DURATION, // duration in ms to keep the cache
})
现在当你从服务器得到响应时,你可以像这样存储它
cache.set(queryId, variables, payload)
读起来像:
cache.get(queryId, variables)
现在对于 observables,从 'relay-runtime';
导入 { Observable }
然后像这样在网络抓取中使用它:
const fetchQuery = (operation, variables) => {
return Observable.create(observer => {
if (operation.operationKind !== 'mutation') {
observer.next(cachedData) // cacheData fetched from cache
}
const jsonResponse = fetch(...);
observer.next(jsonResponse);
observer.complete();
});
};
现在,如果您想要重用来自另一个查询的数据,那么缓存的情况可能不适合您。但是如果你能够从商店获取数据,你应该能够在从服务器获取响应之前使用可观察对象传递数据。
编辑:
Relay 在最初的回复后增加了一些新功能,现在可以像这样实现相同的功能:
// Create relay environment
const environment = new Environment({
network: Network.create(/*...*/),
store,
gcReleaseBufferSize: 10, // Relay will cache the 10 latest responses
});
// Then set fetchPolicy on your QueryRenderer
<QueryRenderer {...otherProps} fetchPolicy="store-and-network" />
中继现在将使用来自商店的响应(如果可用),并且当响应从服务器返回时,使用来自服务器的响应。
我有一个公共的 Header
和 Footer
显示它可能已经在中继存储中的数据和主 PageComponent
期望来自“查询”的数据,但是我不想向用户显示完整的加载屏幕,我想在中间显示页眉、页脚和加载屏幕或内容。
因此,如您所知,如果我将所有内容都包装在 QueryRenderer
中,我将有两个选择:查询正在“加载”或数据可用:
<QueryRenderer
{...usualProps}
render={({ error, props }) => {
<div className="app-wrapper">
{ props || error ? <PageComponent {...props} error={error} /> : <div>Loading...</div>}
</div>
}}
/>
假设我有一种方法可以手动从商店中检索数据(因为我们没有从商店中进行部分渲染之类的东西)并且我可以将该信息传递给公共 Header
和 Footer
加载主查询时:
<QueryRenderer
{...usualProps}
render={({ error, props }) => {
<div className="app-wrapper">
<Header {...storeProps} {...props} />
{ props || error ? <PageComponent {...props} error={error} /> : <div>Loading...</div>}
<Footer {...storeProps} {...props} />
</div>
}}
/>
我发现既然有了环境,我可以做这样的事情来获取商店的信息:
const storeProps = relayEnvironment.getStore().lookup({
dataID: 'client:root',
node: query().fragment, // special query with only the information I need for the `Header`
variables: {}
});
但是我遇到了一些问题:
- QueryRenderer 在卸载时处理数据:cry:(虽然我从中读取的信息也应该由查询检索,但从存储中读取更像是查询时的后备 returns)
- 语法看起来很老套
- 我必须创建一个查询并编译它(无论如何我都可以忍受)
可能我以错误的方式解决了这个问题,也许有人做了类似的事情,可以给我一些建议。
(如果没有任何效果,我的计划 B 是使用 getDerivedStateFromProp
将查询信息发送到自定义上下文并将其保存在那里以避免存储 GC 问题,例如)。
TL:DR: 我想在查询完成加载时从存储中加载数据,然后使用查询返回的数据。
有什么想法吗?如果有什么不清楚的地方,请告诉我
用 relayEnvironment
读取商店听起来不是一个好的解决方案。
如果你为 Header
放一个 QueryRenderer
,为 Footer
放另一个,你会怎么想?所以每个人都会获取自己的数据,与页面内容分开。这有意义吗?
希望对您有所帮助:)
Relay 有 Observables 和 Cache 可以结合使用来实现这个。
您可以从 'relay-runtime';
导入 { QueryResponseCache }然后像这样使用它:
const cache = new QueryResponseCache({
size: CACHE_SIZE, // Number of responses to cache
ttl: CACHE_DURATION, // duration in ms to keep the cache
})
现在当你从服务器得到响应时,你可以像这样存储它
cache.set(queryId, variables, payload)
读起来像:
cache.get(queryId, variables)
现在对于 observables,从 'relay-runtime';
导入 { Observable }然后像这样在网络抓取中使用它:
const fetchQuery = (operation, variables) => {
return Observable.create(observer => {
if (operation.operationKind !== 'mutation') {
observer.next(cachedData) // cacheData fetched from cache
}
const jsonResponse = fetch(...);
observer.next(jsonResponse);
observer.complete();
});
};
现在,如果您想要重用来自另一个查询的数据,那么缓存的情况可能不适合您。但是如果你能够从商店获取数据,你应该能够在从服务器获取响应之前使用可观察对象传递数据。
编辑:
Relay 在最初的回复后增加了一些新功能,现在可以像这样实现相同的功能:
// Create relay environment
const environment = new Environment({
network: Network.create(/*...*/),
store,
gcReleaseBufferSize: 10, // Relay will cache the 10 latest responses
});
// Then set fetchPolicy on your QueryRenderer
<QueryRenderer {...otherProps} fetchPolicy="store-and-network" />
中继现在将使用来自商店的响应(如果可用),并且当响应从服务器返回时,使用来自服务器的响应。