如何合并useLazyQuery多次调用的查询结果?
解决方案:合并useLazyQuery多次调用的缓存结果
完全可行,以下是几种常用的实现方式:
1. 使用update回调手动合并缓存
这是最灵活的方式,你可以在每次查询完成后,自定义合并逻辑,把新数据写入到指定的缓存位置。
假设你的查询是根据id获取单个条目,想要把所有获取到的条目合并到一个缓存列表中:
示例代码:
// 定义获取单个条目的查询 const GET_ITEM = gql` query GetItem($id: ID!) { item(id: $id) { id name description } } `; // 定义用于存储合并结果的客户端查询(无后端对应查询时用@client标记) const GET_ALL_ITEMS = gql` query GetAllItems { allItems @client } `; // 初始化useLazyQuery const [getItem, { loading }] = useLazyQuery(GET_ITEM); const handleGetItem = async (id: string) => { await getItem({ variables: { id }, update: (cache, { data }) => { // 读取现有缓存中的合并结果 const existingData = cache.readQuery({ query: GET_ALL_ITEMS }) || { allItems: [] }; // 避免重复添加相同ID的条目 const itemExists = existingData.allItems.some(item => item.id === data?.item.id); if (!itemExists && data?.item) { // 合并新数据并写回缓存 cache.writeQuery({ query: GET_ALL_ITEMS, data: { allItems: [...existingData.allItems, data.item] } }); } } }); };
如果需要按ID映射存储(方便快速查找),可以调整合并逻辑:
update: (cache, { data }) => { // 读取现有的ID映射缓存 const existingMap = cache.readFragment({ id: 'ItemMap', // 自定义缓存ID fragment: gql` fragment ItemMap on Query { itemsById @client } ` })?.itemsById || {}; if (data?.item) { // 合并新条目到映射中 cache.writeFragment({ id: 'ItemMap', fragment: gql` fragment ItemMap on Query { itemsById @client } `, data: { itemsById: { ...existingMap, [data.item.id]: data.item } } }); } }
2. 统一缓存键(cacheKey)+ 自定义合并
通过给useLazyQuery设置固定的cacheKey,让所有不同变量的查询都指向同一个缓存条目,再结合update逻辑避免覆盖,实现合并。
示例代码:
const [getItem, { loading }] = useLazyQuery(GET_ITEM, { cacheKey: 'mergedItemsCache' // 所有调用共用该缓存键 }); const handleGetItem = async (id: string) => { await getItem({ variables: { id }, update: (cache, { data }) => { // 读取当前缓存键对应的旧数据 const oldData = cache.readQuery({ query: GET_ITEM, cacheKey: 'mergedItemsCache' }); // 合并逻辑(比如合并成数组) const mergedData = { item: [ ...(oldData?.item || []), data?.item ] }; // 写回缓存 cache.writeQuery({ query: GET_ITEM, data: mergedData, cacheKey: 'mergedItemsCache' }); } }); };
注意:这种方式需要确保合并逻辑符合你的数据结构,避免直接覆盖原有缓存。
3. 手动读写缓存(readQuery/writeQuery)
如果需要更精细的控制,可以在查询完成后,手动读取缓存、合并数据、再写回缓存,不依赖update回调:
示例代码:
const handleGetItem = async (id: string) => { const { data } = await getItem({ variables: { id } }); if (!data?.item) return; // 读取现有合并结果 const existingData = cache.readQuery({ query: GET_ALL_ITEMS }) || { allItems: [] }; // 合并数据并去重 const newData = { allItems: [...existingData.allItems, data.item].filter((item, index, self) => index === self.findIndex(i => i.id === item.id) ) }; // 写回缓存 cache.writeQuery({ query: GET_ALL_ITEMS, data: newData }); };
内容的提问来源于stack exchange,提问作者Bruce Lee
相关产品推荐
相关产品推荐

