首页 > 解决方案 > React-Apollo:带变量的查询导致 UI 不再乐观

问题描述

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

这是我的查询:

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用 UI 注释掉键,limit就不会再乐观地更新。注释掉它的值。这里出了什么问题?

标签: reactjsgraphqlapolloreact-apollooptimistic-ui

解决方案


writeQuery方法还接受一个variables值。queryApollo 将和的每个组合variables视为一个单独的查询。因此,如果一个Query组件(或钩子)使用限制,100而另一个使用限制50,则在编写update函数时,您需要调用writeQuery这两个查询,variables每次传入不同的值:

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

这是客户端的已知限制。实际上,您需要通过本地状态跟踪变量,以便在调用函数writeQuery时正确调用。update可以理解,这可能是一个巨大的麻烦。幸运的是,您可以利用apollo-link-watched-mutation来解决这个问题。


推荐阅读