React-Apollo:使用变量进行查询会导致用户界面不再乐观

时间:2019-03-24 16:01:17

标签: reactjs graphql apollo react-apollo optimistic-ui

我正在使用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);
  }
}

我用variables注释掉了limit键后,UI不再乐观地更新。注释掉该值后,它确实起作用。怎么了?

1 个答案:

答案 0 :(得分:1)

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。实际上,您需要通过局部状态跟踪变量,以便在调用writeQuery函数时正确地调用update。可以理解,这可能是一个巨大的麻烦。幸运的是,您可以利用apollo-link-watched-mutation来解决问题。