You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:45:04