Apollo 客户端从缓存中删除项目

Posted

技术标签:

【中文标题】Apollo 客户端从缓存中删除项目【英文标题】:Apollo Client delete Item from cache 【发布时间】:2020-11-21 08:32:35 【问题描述】:

我正在使用带有 React 的 Apollo 客户端。我用许多不同的变量查询帖子。所以我在不同的“缓存”中有一篇文章。现在我想删除一个帖子。所以我需要从所有“缓存”中删除这个特定的帖子。

const client = new ApolloClient(
    link: errorLink.concat(authLink.concat(httpLink)),
    cache: new InMemoryCache()
);

后查询:

export const POSTS = gql`
    query posts(
        $after: String
        $orderBy: PostOrderByInput
        $tags: JSONObject
        $search: String
        $orderByTime: Int
    ) 
        posts(
            after: $after
            orderBy: $orderBy
            tags: $tags
            search: $search
            orderByTime: $orderByTime
        ) 
            id
            title
            ...
        
    
`;

我尝试使用 cache.modify(),它在我的突变中未定义([https://www.apollographql.com/docs/react/caching/cache-interaction/#cachemodify][1])

const [deletePost] = useMutation(DELETE_POST, 
        onError: (er) => 
            console.log(er);
        ,
        update(cache, data) 
            console.log(cache.modify())//UNDEFINED!!!
            cache.modify(
                id: cache.identify(thread), //identify is UNDEFINED + what is thread
                fields: 
                    posts(existingPosts = []) 
                        return existingPosts.filter(
                            postRef => idToRemove !== readField('id', postRef)
                         );
                    
                
            )
        
    );

我也使用了 useApolloClient() ,结果相同。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

您可以将更新程序传递给useMutationdeletePostdeletePost 应该更容易,因为它可能知道它试图删除什么:

    deletePost(
        variables:  idToRemove ,
        update(cache) 
            cache.modify(
                fields: 
                    posts(existingPosts = []) 
                        return existingPosts.filter(
                            postRef => idToRemove !== readField('id', postRef)
                        );
                    ,
                ,
            );
        ,
    );

您应该更改 variables 以匹配您的突变。这应该可以工作,因为posts 位于查询的顶层。对于更深的字段,您需要一种方法来获取父对象的 id。 readQuery 或顶部的 readField 链可能会帮助您。

【讨论】:

【参考方案2】:

这个选项对我有用

const GET_TASKS = gql`
  query tasks($listID: String!) 
    tasks(listID: $listID) 
      _id
      title
      sort
    
  
`;

const REMOVE_TASK = gql`
  mutation removeTask($_id: String) 
    removeTask(_id: $_id) 
      _id
    
  
`;

const Tasks = () => 
  const  loading, error, data  = useQuery(GET_TASKS, 
    variables:  listID: '1' ,
  );
  сonst [removeTask] = useMutation(REMOVE_TASK);

  const handleRemoveItem = _id => 
    removeTask(
      variables:  _id ,
      update(cache) 
        cache.modify(
          fields: 
            tasks(existingTaskRefs,  readField ) 
              return existingTaskRefs.filter(
                taskRef => _id !== readField('_id', taskRef),
              );
            ,
          ,
        );
      ,
    );
  ;

  return (...);
;

【讨论】:

【参考方案3】:

您可以使用cache.evict,而不是使用cache.modify,这使得代码更短:

deletePost(
    variables:  id ,
    update(cache) 
        const normalizedId = cache.identify( id, __typename: 'Post' );
        cache.evict( id: normalizedId );
        cache.gc();
    
);

【讨论】:

这种情况下需要cache.gc()吗? 我认为是的,apollographql.com/docs/react/caching/garbage-collection/… 说:“驱逐一个对象通常会使其他缓存的对象无法访问。因此,您应该在从缓存中驱逐一个或多个对象后调用 cache.gc。”

以上是关于Apollo 客户端从缓存中删除项目的主要内容,如果未能解决你的问题,请参考以下文章

删除 Apollo 3 上的缓存

使用 Apollo 链路状态缓存实现客户端过滤

ReactJS:Apollo graphql 客户端。缓存不在本地更新

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

Apollo 客户端 - 从缓存中读取

创建突变后添加到 Apollo 客户端缓存中的数组