Apollo 客户端 fetchMore 来自 useQuery 触发两个网络请求

Posted

技术标签:

【中文标题】Apollo 客户端 fetchMore 来自 useQuery 触发两个网络请求【英文标题】:Apollo client fetchMore from useQuery fires two network requests 【发布时间】:2022-01-06 22:43:18 【问题描述】:

我正在尝试实现loadMore 功能,该功能使用useQueryfetchMore 功能将项目附加到原始列表中。

const  data, fetchMore  = useQuery(GET_PODCAST_SERIES, 
    variables: 
      limit: 12,
      offset: 0,
      pathOrId: `$site/podcast/$slug`,
    ,
    nextFetchPolicy: 'cache-first',
  );

const length = data.PodcastSeriesQuery.podcastSeries.podcastEpisodes.length;

return <..>
  ...
   <button onClick=() => 
       fetchMore(
         variables:  offset: length  
       )
    >load more</button>
</..>

查询看起来像这样

const GET_PODCAST_SERIES = gql`
  query PodcastSeries($pathOrId: String, $limit: Int, $offset: Int) 
    PodcastSeriesQuery(pathOrId: $pathOrId) 
      podcastSeries(limit: $limit, offset: $offset) 
        id
        ...
        podcastEpisodes 
          id
          ...
        
      
    
  
`;

缓存看起来像这样

cache: new InMemoryCache(
      typePolicies: 
        Query: 
          fields: 
            PodcastSeriesQuery: 
              keyArgs: ['pathOrId'],
              merge(_, incoming) 
                return incoming;
              ,
            ,
          ,
        ,
        PodcastSeries: 
          fields: 
            podcastEpisodes: 
              merge(existing = [], incoming) 
                return [...existing, ...incoming];
              ,
            ,
          ,
        ,
      ,
    ),

问题是每当我调用fetchMore 时,它都会发送两个网络请求,而默认的总是会触发。例如

第一次点击加载更多

 - network request 1 -> offset: 12, limit: 12, pathOrId: ...

 - network request 2 -> offset: 0, limit: 12, pathOrId: ...

第二次点击加载更多

  - network request 1 -> offset: 36 (even thought it should be 24, but it is still correct because the first click fetches twice making the data.list bigger), limit: 12, pathOrId: ...

  - network request 2 -> offset: 0, limit: 12, ....

所以默认查询总是被触发..

我应该如何解决这个问题?谢谢。

【问题讨论】:

【参考方案1】:

这只是因为缓存不正确。我通过这样做解决了它

cache: new InMemoryCache(
      typePolicies: 
        Query: 
          fields: 
            PodcastSeriesQuery: 
              keyArgs: ['pathOrId'],
              merge(existing, incoming) 
                // before -> return incoming || existing;
                return existing || incoming; // after
              ,
            ,
          ,
        ,
        PodcastSeries: 
          fields: 
            podcastEpisodes: 
              merge(existing = [], incoming) 
                return [...existing, ...incoming];
              ,
            ,
          ,
        ,
      ,
    ),

【讨论】:

以上是关于Apollo 客户端 fetchMore 来自 useQuery 触发两个网络请求的主要内容,如果未能解决你的问题,请参考以下文章

在具有“合并”功能的 apollo 客户端分页配置中,即使调用 fetchMore,现有缓存数据也始终为空

Apollo fetchMore 更新的 props 不重新渲染组件

UseApolloClient 查询不会返回 fetchMore

TypeError:无法读取 Apollo 中未定义的属性“fetchMore”

fetchMore 导致页面意外重新渲染

React/Apollo fetchMore 重新加载整个页面