Apollo Client (React) 分页/排序数据缓存添加新项后更新方案咨询
可选方案推荐
方案1:配置GraphQL客户端缓存字段策略(实现成本最低,推荐)
- 如果你使用的是Apollo Client、Relay这类主流GraphQL客户端,直接在缓存的TypePolicy中为
Query.items字段配置自定义read/merge函数即可:merge函数负责把每次查询返回的条目正常写入缓存read函数在读取该字段结果时,自动拉取缓存中所有同类型的条目,根据当前查询携带的分页、排序参数过滤符合条件的条目,合并到当前查询的结果集中,按排序规则调整顺序后返回
- 你只需要在新增条目成功后,把新条目对象写入缓存,所有活跃的
items查询都会自动判断新条目是否符合当前视图规则,符合的话会自动插入到对应位置,完全不需要手动定位查询缓存或传递分页排序参数。
示例参考(以Apollo Client为例):
const cache = new InMemoryCache({ typePolicies: { Query: { fields: { items: { read(existing, { args, readField }) { // 从缓存读取所有对应类型的条目 const allItems = Object.values(cache.data.data).filter(obj => obj.__typename === '替换为你的条目类型名') // 按当前查询的排序参数排序 const sorted = allItems.sort((a, b) => { const sortField = args.pagingAndSorting.sorting.field const sortDir = args.pagingAndSorting.sorting.direction const valA = readField(sortField, a) const valB = readField(sortField, b) return sortDir === 'asc' ? valA.localeCompare(valB) : valB.localeCompare(valA) }) // 按分页参数截取当前页数据 const startIndex = (args.pagingAndSorting.pageNumber - 1) * args.pagingAndSorting.pageSize const endIndex = startIndex + args.pagingAndSorting.pageSize return sorted.slice(startIndex, endIndex) }, merge(existing, incoming) { return incoming } } } } } })
方案2:新增后遍历活跃查询按需更新缓存
- 大部分GraphQL客户端都支持获取当前被组件订阅的所有活跃查询列表,你可以在新增条目成功后:
- 拿到新条目的完整数据
- 遍历所有活跃的
items查询,拿到每个查询对应的分页、排序参数 - 判断新条目是否符合该查询的规则,是否应该出现在当前页
- 符合的话直接将新条目插入到该查询缓存的
data数组对应位置即可,不符合则跳过
- 该方案不需要提前存储分页排序参数,也不需要触发网络请求,性能开销极低。
方案3:依赖触发自动重查
- 在列表页维护一个
lastUpdateTime的状态变量,将该变量作为查询的响应式依赖 - 新增条目成功后全局更新这个
lastUpdateTime的值,列表查询会自动使用当前绑定的分页、排序参数重新请求最新数据,不需要你手动传递、存储任何查询参数,实现成本极低,适合复杂度不高的项目。
你漏掉的缓存更新逻辑
你之前直接新增对象不生效,是因为GraphQL客户端默认的缓存策略是按查询参数隔离结果集,不会自动跨查询合并同类型数据,只要加上文的字段策略配置,就能实现新增条目自动同步到符合条件的列表视图,是目前最简单的解法。
内容的提问来源于stack exchange,提问作者Brett DeWoody
相关产品推荐
相关产品推荐

