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

Anilist GraphQL分页查询Apollo缓存分离与合并问题咨询

解决方案

1. 让缓存区分ANIME与MANGA类型的Page数据

方案A:将media类型转为查询变量

把原查询中写死的type: "ANIME"/type: "MANGA"改成变量参数,这样不同类型的查询会因变量差异生成独立缓存条目:

统一查询模板:

query MediaPage($page: Int, $perPage: Int, $type: MediaType!) {
  Page(page: $page, perPage: $perPage) {
    media(type: $type) {
      id
      title {
        romaji
      }
    }
  }
}
  • Anime页面调用时,传入变量:{ page: 1, perPage: 20, type: "ANIME" }
  • Manga页面调用时,传入变量:{ page: 1, perPage: 20, type: "MANGA" }

Apollo会自动根据不同的$type变量生成独立缓存键,彻底避免缓存覆盖问题。

方案B:自定义缓存键函数(Apollo Client 3+)

若无法修改原有查询结构,可通过cacheKeyFn为Page对象生成包含媒体类型的唯一缓存键,在Apollo Client配置中添加:

const client = new ApolloClient({
  uri: 'https://graphql.anilist.co',
  cache: new InMemoryCache({
    cacheKeyFn: (obj, options) => {
      if (obj.__typename === 'Page') {
        // 从查询参数中提取媒体类型,生成唯一键
        const mediaType = options.field?.args?.type || options.variables?.type;
        return `Page:${mediaType}:${obj.page || ''}`;
      }
      // 其他类型沿用默认逻辑
      return defaultDataIdFromObject(obj);
    },
  }),
});

2. 分页时合并对应类型的media列表

方案A:fetchMore + updateQuery手动合并

分页加载时,通过fetchMore发起请求,并在updateQuery中手动将新数据追加到缓存列表:

// Anime页面示例
const { data, fetchMore } = useQuery(MediaPage, {
  variables: { page: 1, perPage: 20, type: "ANIME" },
});

const loadNextPage = () => {
  fetchMore({
    variables: { page: data.Page.page + 1 },
    updateQuery: (prevResult, { fetchMoreResult }) => {
      if (!fetchMoreResult) return prevResult;
      return {
        Page: {
          ...prevResult.Page,
          media: [...prevResult.Page.media, ...fetchMoreResult.Page.media],
          page: fetchMoreResult.Page.page,
        },
      };
    },
  });
};

方案B:@connection指令自动处理分页

在查询中添加@connection指令,指定包含媒体类型的唯一连接名称,让Apollo自动合并分页数据:

query MediaPage($page: Int, $perPage: Int, $type: MediaType!) {
  Page(page: $page, perPage: $perPage) {
    media(type: $type) @connection(key: "MediaList_$type") {
      id
      title {
        romaji
      }
    }
  }
}

key: "MediaList_$type"会自动代入$type变量,生成MediaList_ANIME和MediaList_MANGA两个独立缓存,Apollo会自动完成后续分页数据的合并,无需手动编写更新逻辑。

额外提示

  • 不要用清空缓存的方式解决问题,这会导致重复请求,降低用户体验。
  • 优先选择「方案1A + 方案2B」的组合,代码简洁且符合Apollo最佳实践。

内容的提问来源于stack exchange,提问作者Stas Motorny

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 04:32:05