React-Apollo: запрос с переменными приводит к тому, что пользовательский интерфейс перестает быть оптимистичным - PullRequest
0 голосов
/ 24 марта 2019

Я пишу компонент React с использованием Apollo GraphQL (с 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 с помощью limit, пользовательский интерфейс больше не обновляется оптимистически.С закомментированным значением это делает.Что здесь не так?

1 Ответ

1 голос
/ 24 марта 2019

Метод writeQuery также принимает значение variables. Каждая комбинация query и variables рассматривается Apollo как отдельный запрос. Поэтому, если один компонент 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 , чтобы обойти эту проблему.

...