我们在电子商务网站中广泛使用了Apollo GraphQl,当路线改变时,我遇到一些不必要的闪烁问题。
我的ProductTypeFilter
组件包装在Router
和Query
组件中。 Query
使用来自路由的信息作为其变量,在本示例中为productTypeId
。
export const ProductTypeFilterContainer = () => (
<Router>
{({ query: { productTypeId } }) => (
<Query query={GET_PRODUCT_FILTERS} variables={{ productTypeId }}>
{({ error, loading, data: { productFilters } }) => {
if (loading || error) {
return null
}
return <ProductTypeFilter productFilters={productFilters} />
}}
</Query>
)}
</Router>
)
null
在短时间内被渲染,并且当数据到达时ProductTypeFilter
被渲染。这可以按预期工作。
但是,当用户导航到其他产品类型时,ProductTypeFilter
将被卸载,然后使用新数据重新装载。只要查询加载,就会呈现 null
,这确实会引入不必要的“闪烁” 。
这仅在用户第一次访问产品类型时发生,而这是第二次Apollo缓存找到query
和variables
的相同组合并立即呈现ProductTypeFilter
时。
我不能使用state
,因为在渲染函数中不允许调用setState
。似乎唯一有效的方法是引入一个全局变量,该变量用于呈现并在新数据到达时进行更新:
let previousFilters = undefined
...
if (!error && previousFilters && !productFilters) {
productFilters = previousFilters
}
if (error || productFilters) {
return null
}
previousFilters = productFilters
return <ProductTypeFilter productFilters={productFilters} />
有没有能让我鸡皮ump更好的东西?
答案 0 :(得分:1)
Apollo将重新获取查询,将loading设置为true,并在每次安装该组件时返回null。
尽管(如果您具有Apollo缓存设置)它已经将数据存储在缓存中,它仍会执行此操作。
我建议像下面的伪代码那样对您的代码重新排序:
// it's a good idea to let your users know if something goes wrong
if(error) return ErrorMessage
// note it's before loading
if(data) return ProductTypeFilter
// it's a good idea to let your users know there is some activity
if(loading) return LoadingIndicator
这样,您将看到加载指示符,或者在第一次加载时为null,但是如果已缓存,则立即看到数据-不闪烁。