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

时间:2021-01-22 20:35:54

标签: reactjs graphql apollo-client

在这里看到了类似的问题,但无法解决这些问题。我是功能组件和 Apollo Client 的新手,在阅读 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;

你能帮我理解我在这里遗漏了什么吗?

1 个答案:

答案 0 :(得分:2)

您没有在 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]}
    });
  };