React-Apollo:带变量的查询导致 UI 不再乐观

React-Apollo: Query with variables causes the UI to no longer be optimistic

我正在使用 Apollo GraphQL(使用 React Apollo Hooks,但这没有区别)编写一个 React 组件。

这是我的查询:

const { data, error, loading } = useQuery(ListContacts, {
  fetchPolicy: 'cache-and-network'
  // variables: { limit: 1000 }
});

这是我执行突变的函数:

const createContact = useMutation(gql(mutations.createContact));
const deleteContact = useMutation(gql(mutations.deleteContact));
const updateContact = useMutation(gql(mutations.updateContact));

async function handleContactSave(contact) {
  const isEmpty = allStringFieldsAreEmptyFromContact(contact);
  const { id, ...processedContact } = replaceEmptyStringsWithNull(contact);
  const idIsInArray = includesContactWithId(id)(contacts);

  try {
    if (isEmpty) {
      if (idIsInArray) {
        await deleteContact({
          variables: { input: { id } },
          optimisticResponse: () => ({ deleteContact: { id } }),
          update: (cache, { data: { deleteContact } }) => {
            const query = ListContacts;
            const data = cache.readQuery({ query });
            data.listContacts.items = data.listContacts.items.filter(
              item => item.id !== deleteContact.id
            );
            cache.writeQuery({ query, data });
          }
        });
      }
    } else {
      if (idIsInArray) {
        await updateContact({
          variables: { input: { id, ...processedContact } },
          optimisticResponse: () => ({
            updateContact: { __typename: 'Contact', id, ...processedContact }
          }),
          update: (cache, { data: { updateContact } }) => {
            const query = ListContacts;
            const data = cache.readQuery({ query });
            data.listContacts.items = [
              ...data.listContacts.items.filter(
                item => item.id !== updateContact.id
              ),
              updateContact
            ];
            cache.writeQuery({ query, data });
          }
        });
      } else {
        await createContact({
          variables: { input: { ...processedContact } },
          optimisticResponse: () => ({
            createContact: {
              __typename: 'Contact',
              id: uuid(),
              ...processedContact
            }
          }),
          update: (cache, { data: { createContact } }) => {
            const query = ListContacts;
            const data = cache.readQuery({ query });
            data.listContacts.items = [
              ...data.listContacts.items.filter(
                item => item.id !== createContact.id
              ),
              createContact
            ];
            cache.writeQuery({ query, data });
          }
        });
      }
    }
  } catch (error) {
    console.log(error);
  }
}

一旦我用 limit 注释掉 variables 键,UI 就不会再乐观地更新了。注释掉它的值。这里出了什么问题?

writeQuery 方法也接受 variables 值。 queryvariables 的每个组合都被 Apollo 视为单独的查询。因此,如果一个 Query 组件(或挂钩)使用 100 的限制而另一个使用 50 的限制,则在编写 update 函数时,您需要调用writeQuery 对于这两个查询,每次都为 variables 传递不同的值:

cache.writeQuery({ query, data, variables: { limit: 100 } })
cache.writeQuery({ query, data, variables: { limit: 50 } })

这是 know limitation of the client. In effect, you need to keep track of the variables through local state in order to correctly call writeQuery when your update function is called. This can be, understandably, a huge hassle. Luckily, you can utilize apollo-link-watched-mutation 解决问题的方法。