Автоматическое обновление клиентского кэша Apollo после мутации, не затрагивающей существующие запросы - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть мутация (UploadTransaction), возвращающая определенный список определенного объекта с именем Transaction.

#import "TransactionFields.gql" 
mutation UploadTransaction($files: [Upload!]!) {
  uploadFile(files: $files){
    transactions {
      ...TransactionFields
    }
  }
}

Транзакция, возвращаемая из бэкэнда (графена), имеет поля id и typename. Следовательно, он должен автоматически обновлять транзакцию в кеше. В chrome инструментах разработчика для Apollo я вижу новые транзакции:

enter image description here

У меня также есть запрос GetTransactions, извлекающий все объекты транзакций.

#import "TransactionFields.gql"
query GetTransactions {
  transactions {
    ...TransactionFields
  }
}

Однако я не вижу, что запрос добавил новую транзакцию. Во время начальной загрузки клиент Apollo загрузил 292 транзакции, которые он показывает под ROOT_QUERY. Он продолжает возвращать те же 292 транзакции. Мутация UploadTransaction добавляет новый объект типа «Транзакция» в кэш в dev-tools, не затрагивая ROOT_QUERY в dev-tools или мой запрос в коде.

enter image description here

TransactionFields.gql - это

fragment TransactionFields on Transaction {
    id
    timestamp
    description
    amount
    category {
      id
      name
    }
    currency
}

Есть идеи, что я делаю не так? Я новичок в клиентах apollo и graphql

1 Ответ

1 голос
/ 23 февраля 2020

Из документов :

Если мутация обновляет одну существующую сущность, Apollo Client может автоматически обновить значение этой сущности в своем кэше, когда мутация возвращается. Для этого мутация должна вернуть идентификатор измененного объекта вместе со значениями полей, которые были изменены. Удобно, что мутации делают это по умолчанию в клиенте Apollo ...

Если мутация изменяет несколько сущностей или если она создает или удаляет сущности, кеш клиента Apollo автоматически равен , а не обновлен, чтобы отразить результат мутации. Чтобы решить эту проблему, ваш вызов useMutation может включать функцию обновления.

Если у вас есть запрос, который возвращает список объектов (например, пользователи), а затем создать или удалить пользователя, Apollo не может знать, что список должен быть обновлен, чтобы отразить вашу мутацию. Причина этого двоякая

  • У Аполлона нет возможности узнать , что на самом деле делает мутация . Все, что он знает, это то, какие поля вы запрашиваете и какие аргументы вы передаете этим полям. Можно предположить, что мутация, включающая такие слова, как «вставить» или «создать», вставляет что-то в бэкэнд, но это не дано.
  • Нет способа узнать, что вставка, удаление или обновление пользователя должен обновить конкретный запрос. Ваш запрос может относиться ко всем пользователям с именем «Bob» - если вы создаете пользователя с именем «Susan», запрос не должен обновляться, чтобы отразить это дополнение. Точно так же, если мутация обновляет пользователя, запрос может должен быть обновлен, чтобы отразить изменение. Должно ли это в конечном итоге сводиться к бизнес-правилам, о которых знает только ваш сервер.

Итак, для обновления кэша у вас есть два варианта:

  • Запустите повторное получение соответствующих запросов. Вы можете сделать это, передав опцию refetchQueries на хук useMutation, или , вручную вызвав refetch для этих запросов . Поскольку для этого требуется один или несколько дополнительных запросов к вашему серверу, это более медленный и более дорогой вариант, но он может быть правильным вариантом, когда А) вы не хотите внедрять кучу бизнес-логик c в свой клиент или Б) Обновления кеша сложны и обширны.
  • Предоставьте update функцию для вашего useMutation хука, которая сообщает Apollo , как обновить кеш на основе результатов мутации. Это избавляет вас от выполнения каких-либо дополнительных запросов, но означает, что вам придется дублировать некоторые бизнес-логики c между вашим сервером и вашим клиентом.

Пример использования update из документов:

update (cache, { data: { addTodo } }) {
  const { todos } = cache.readQuery({ query: GET_TODOS });
  cache.writeQuery({
    query: GET_TODOS,
    data: { todos: todos.concat([addTodo]) },
  });
}

Прочтите документы для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...