轮询不工作时更新 Apollo 客户端 3 的缓存

Posted

技术标签:

【中文标题】轮询不工作时更新 Apollo 客户端 3 的缓存【英文标题】:Update the cache of Apollo client 3 when polling not working 【发布时间】:2021-01-18 09:12:00 【问题描述】:

我正在玩@apollo/client v3 的缓存。这是codesandbox。

我正在使用client.writeQuery 将一个用户添加到缓存的用户列表中,并且查询有一个pollInterval 每隔几秒重新获取一次。

我可以将用户添加到列表中,它会刷新 UI,并且我可以看到 pollInterval 在 Chrome 的 network 选项卡中工作。

问题

我希望用户列表在轮询开始时返回到其初始状态,并覆盖我手动添加到缓存中的用户,但事实并非如此。

阿波罗配置

export const cache = new InMemoryCache();

const client = new ApolloClient(
  cache,
  link: new HttpLink(
    uri: "https://fakeql.com/graphql/218375d695835e0850a14a3c505a6447"
  )
);

用户列表

export const UserList = () => 
  const  optimisticAddUserToCache, data, loading  = useUserList();

  if (loading) 
    return <div>Loading...</div>;
  

  return (
    <div>
      <button onClick=() => optimisticAddUserToCache()>Add User to cache</button>
      <ol>
        data?.users.map(user => 
          return <li key=user.id>user.firstname</li>;
        )
      </ol>
    </div>
  );

使用用户列表

const GET_USER_LIST = gql`
  query Users 
    users 
      id
      firstname
    
  
`;

export const useUserList = () => 
  const  loading, error, data, refetch  = useQuery(GET_USER_LIST, 
    pollInterval: 4000 // It does poll (check chromes's network tab), but it doesn't seem to overwrite the cache
  );
  const client = useApolloClient();

  const optimisticAddUserToCache = () => 
    const newUser: any = 
      id: `userId-$Math.random()`,
      firstname: "JOHN DOE",
      __typename: "User"
    ;

    const currentUserList = client.readQuery( query: GET_USER_LIST ).users;

    // This works, it does add a user, and UI refreshes.
    client.writeQuery(
      query: GET_USER_LIST,
      data: 
        users: [newUser, ...currentUserList]
      
    );
  ;

  return  optimisticAddUserToCache, loading, error, data, refetch ;
;

【问题讨论】:

【参考方案1】:

按预期工作(几乎)

轮询响应总是带有相同的数据 ...

... 不会导致写入缓存(不比较内容)...

...缓存中没有数据更改...

...data 属性(来自useQuery)未更新...

...没有data 更新,没有组件重新渲染。

要进行乐观更新,您需要真正的突变,远程数据源上的真正[持久]更改...传播到下一个轮询响应。

【讨论】:

这是我正在开发的一个大型应用程序的简短版本。在应用程序中,我正在做完全相同的事情,它有时有效,有时没有。我不知道为什么。但我可以告诉你,我从不对数据使用突变。为什么“......不会导致写入缓存(没有比较内容)......”?轮询数据实际上与缓存中的数据不同,因此应该进行比较?我很确定有一个不使用突变的解决方案,因为我说过我不使用它们并且它在我的应用程序中间歇性地工作。 轮询数据等于先前轮询的数据...响应数据未与缓存条目进行比较...可能应该进行比较(在 github 上发布问题?)...外部突变源?为什么不使用订阅(而不是轮询)? 我也在github上发帖以防万一。我只使用 GraphQL 来读取数据,而不是写入,因此我根本不使用突变。我们也有订阅,但在这种特殊情况下,我真的想了解缓存是如何工作的,所以除非我正在做的方式是绝对不可能的(我不这么认为,正如我所说的我有这一半在我的主应用程序上工作),我真的很想让我的示例工作。 看起来与github.com/apollographql/apollo-client/issues/6925相关

以上是关于轮询不工作时更新 Apollo 客户端 3 的缓存的主要内容,如果未能解决你的问题,请参考以下文章

Apollo 客户端:更新缓存时的 writeFragment 或 readFragment?

当变量发生变化时,Apollo 客户端缓存不会在查询中更新

PHP + jQuery - 使用数据库数据进行长轮询不起作用(它不会打破循环)

在 Apollo 客户端上更新缓存

Apollo 客户端:缓存更新后组件不呈现(反应变量)

写入缓存时,Apollo 客户端链接状态“ 中缺少字段”?