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

Posted

技术标签:

【中文标题】Apollo 客户端:缓存更新后组件不呈现(反应变量)【英文标题】:Apollo Client: Component doesn't render after cache update (reactive variables) 【发布时间】:2021-04-27 08:22:20 【问题描述】:

在这里看到了类似的问题,但我无法解决这些问题。我是功能组件和 Apollo 客户端的新手,在阅读 documentation 之后,创建了一个应该呈现项目列表的组件,然后(在添加时)更新缓存并从中读取,再次呈现组件。但是结果是不同的,我不明白为什么组件没有渲染。使用了 Apollo Client 和反应变量。

这是我的cache.js

import  InMemoryCache, makeVar  from "@apollo/client";

export const cache = new InMemoryCache(
  dataIdFromObject: (object) => object.key,
  typePolicies: 
    Query: 
      fields: 
        items: 
          read() 
            return itemsVar();
          ,
        ,
      ,
    ,
  ,
);

export const itemsVar = makeVar([]);

export default cache;

然后,我有以下组件:

import React,  useState, Fragment  from "react";
import  useQuery, useReactiveVar, useMutation  from "@apollo/client";
import GET_ALL_ACTIVE_ITEMS from "../../queries/Item";
import CREATE_ITEM from "../../mutations/Item";

import  itemsVar  from "../../cache";

//Components
import Item from "./Item";

const ItemContainer = () => 
  // this gets the list of items upon component loading
  const  data  = useQuery(GET_ALL_ACTIVE_ITEMS);

  // Input to create the new Item
  const [itemInput, setItemInput] = useState(
    title: "",
  );

  const [createItem] = useMutation(CREATE_ITEM);

  const onAddItemClick = (e) => 
    e.preventDefault();
    createItem(
      variables: 
        itemInput: itemInput,
      ,
    ).then((res) => 
      // Gets the result of the created Item and adds to cached
      let resArray = [...res.data.itemInput];
      itemsVar([...itemsVar().getAllActiveItems, resArray]);
    );
  ;

  const onChange = (e) => 
    setItemInput( ...itemInput, [e.target.name]: e.target.value );
  ;

  // Sets the cache reactive variable to the data from the backend
  itemsVar(data);
  const items = useReactiveVar(itemsVar);

  return (
    <div>
      <div>
        <div onClick=onAddItemClick className="primary-button">
          Add item
        </div>
           <input
            type="text"
            name="title"
            value=itemInput.title
            onChange=onChange
          />
      </div>
      items && items.getAllActiveItems.length === 0 ? (
        <p>No items</p>
      ) : (
        <Fragment>
          items &&
            items.getAllActiveItems.map(( _id, title ) => (
              <Item key=_id title=title />
            ))
        </Fragment>
      )
    </div>
  );
;

export default ItemContainer;

此组件在加载时正确呈现项目。现在,即使它创建了一个新项目,它也不会刷新组件(我假设缓存也没有更新,尽管不确定)。

获取所有项目查询:

import gql from "graphql-tag";

const GET_ALL_ACTIVE_ITEMS = gql`
  query getAllActiveItems() 
    getAllActiveItems() 
      _id
      title
    
  
`;

export default GET_ALL_ACTIVE_ITEMS;

创建项目查询,它创建一个项目并将其作为数组返回:

import gql from "graphql-tag";

const CREATE_ITEM = gql`
  mutation createItem($itemInput: CreateItemInput!) 
    createItem(itemInput: $itemInput) 
      _id
      title
    
  
`;

export default CREATE_ITEM;

你能帮我理解我在这里缺少什么吗?

【问题讨论】:

'突变后缓存更新' - 阅读文档 @xadm 与反应变量一样吗? 【参考方案1】:

您没有指定是否要更新缓存或不在 useMutation 挂钩中。

useMutation 钩子也接受选项,如下所示:-

function useMutation<TData = any, TVariables = OperationVariables>(
  mutation: DocumentNode,
  options?: MutationHookOptions<TData, TVariables>,
): MutationTuple<TData, TVariables> 

因此,如果您想在发生突变后更新缓存,请使用

const [createItem] = useMutation(CREATE_ITEM,update: updateCache);



const updateCache = (cache, data) => 
    
    // Fetch from the cache
    const existingItems = cache.readQuery(
      query: GET_ALL_ACTIVE_ITEMS
    );
    // Add to the cache
    const newItem = ....
    cache.writeQuery(
      query: GET_ALL_ACTIVE_ITEMS,
      data: items: [newItem, ...existingItems]
    );
  ;

【讨论】:

谢谢!在我的情况下 updateCache 将是反应变量本身? 你需要读写缓存,我已经更新了答案。 @Ruham

以上是关于Apollo 客户端:缓存更新后组件不呈现(反应变量)的主要内容,如果未能解决你的问题,请参考以下文章

Apollo 客户端(反应) - 无法更新未安装组件的状态

如何使用 React HashRouter 和 Apollo 客户端渲染反应类组件?

子组件中的缓存未更新

如何在突变之前更新 apollo 缓存状态,以进行 Like、Upvote 等操作? [关闭]

在 Apollo-client 中,writeQuery 会更新缓存,但 UI 组件不会重新渲染

查询后如何更新 Apollo 缓存?