反应应用程序上的 Apollo 客户端缓存问题

Posted

技术标签:

【中文标题】反应应用程序上的 Apollo 客户端缓存问题【英文标题】:Issue with Apollo Client cache on a react app 【发布时间】:2021-02-26 12:32:42 【问题描述】:

在获取基于类别返回文章列表的端点时,我遇到了一个问题。

我已经设置了一个带有 apollo 客户端的 React 应用程序,该客户端包装了所有内容 (index.tsx):

const client = new ApolloClient(
  uri: myurl,
  cache: new InMemoryCache(),
);

ReactDOM.render(
  <ThemeProvider theme=theme>
    <ApolloProvider client=client>
      <Router>
        <App />
      </Router>
    </ApolloProvider>
  </ThemeProvider>,

  document.getElementById("root")
);

然后我在菜单中有一个&lt;Link to=news/$cat /&gt; 列表,当我单击菜单时,它会正确导航到news/1234

从页面中,我获得了我需要的类别,然后将其用作我的 graphql 查询的变量。

由于我有客户端包装整个应用程序,我使用ApolloConsumer 像这样传递客户端:

const CategoryArticlesList = ( location, match : RouteChildrenProps) => 
  return (
    <ApolloConsumer>
      (client) => 
        return (
          <ListAllArticles location=location match=match client=client />
        );
      
    </ApolloConsumer>
  );
;

然后,从&lt;ListAllArticles&gt; 组件,我得到了这段简化的代码:

const getNewsBycategory = gql`
  query($page: Int, $cid: String) 
    News(page: $page, categoryId: $cid) 
      results 
        category
        category_id
        title
        date
        body_preview
        is_published
        thumbnail_s
        id
      
      extra 
        pagination 
          total_items
          limit
        
      
    
  
`;


const pageToFetch = "1"
const categoryId = match.params.categoryId || "1234";

  const variables = React.useMemo(
    () => (
      page: pageToFetch,
      categoryId: categoryId,
    ),
    [categoryId, pageToFetch]
  );

  const  data, loading, error  = useQuery(getNewsBycategory, 
    variables:  ...variables ,
  );

当我更改页面时,URL 中的类别发生了变化,使用新的和更新的 categoryID 变量执行查询(我检查了网络选项卡),但结果与以前相同。

我认为这是一个缓存问题,所以我尝试将"no-cache""network-only" 更改为fetchPolicy,但我遇到了同样的问题。

您能否建议为什么会发生这种情况以及我该如何克服?

非常感谢您提供任何帮助/建议

【问题讨论】:

你有没有建立组件? 是的,路由在所有其他页面上也可以正常工作 当你说结果和以前一样——你的意思是组件没有重新渲染,还是通过网络返回的数据是一样的? 将 fetchPolicy 保持为“仅限网络”,并在导航到新路线后使用 Apollo devtools 查看缓存...可能会有所帮助 感谢您推荐 apollo devtools。当我说结果与之前相同时,我的意思是网络返回相同的数据,就像根本不考虑类别一样 【参考方案1】:

最后,我设法找到了问题。

我是这样调用我的查询的:

export const query = gql`
  query($page: Int, $cid: String) 
    News(page: $page, categoryId: $cid) 
      results 
        category
        category_id
        title
        date
        body_preview
        is_published
        thumbnail_s
        id
      
    
  
`;

如您所见,我将变量 $cid 传递给 categoryId(服务器上的查询需要此名称)。 我以为我可以为该变量取我想要的名称,但结果表明,将变量用作 $cid 而不是 $categoryId 并没有在查询中发送变量。

将我的查询更改为如下所示:

export const getNewsBycategory = gql`
  query($page: Int, $categoryId: String) 
    News(page: $page, categoryId: $categoryId) 
      results 
        category
        category_id
        title
        date
        body_preview
        is_published
        thumbnail_s
        id
      
    
  
`;

解决了问题。

直到现在我才知道这个变量命名的事情,奇怪的是,从网络上我可以看到变量被发送出去,但只有调试服务器我才发现它并没有真正被发送出去结束

【讨论】:

它可以与包含 'cid' 属性的变量一起使用...变量必须匹配第一个括号 args,而不是第二个

以上是关于反应应用程序上的 Apollo 客户端缓存问题的主要内容,如果未能解决你的问题,请参考以下文章

Apollo 客户端持久缓存不起作用

缓存对象上的 Apollo 客户端查询重复数据删除

使用 writeQuery() 更新 Apollo 客户端上的缓存

删除 Apollo 3 上的缓存

Apollo 客户端 devtool 无法在反应本机应用程序中检测到 Apollo 客户端

Apollo 客户端/使用 localhost 反应本机错误