Это руководство с некоторыми из общих шаблонов доступа и управления хранилищем / кешем в React Apollo GraphQL. В качестве примера прочтите https://www.apollographql.com/docs/react/essentials/get-started.html#installation

Прямой доступ к кешу

Для доступа к кэшу данных вы можете использовать методы класса Apollo Client readQuery, readFragment, writeQuery и writeFragment через интерфейс DataProxy.

readQuery

readQuery никогда не будет делать запросы к вашему серверу GraphQL. Он всегда будет читать из кеша, иначе throw возникнет ошибка; поэтому убедитесь, что вы читаете только те данные, которые, как вы знаете, есть в магазине.

В качестве альтернативы метод query может отправить запрос на ваш сервер, если соответствующие данные отсутствуют в вашем кеше.

readFragment

readFragment позволяет вам читать данные с любого узла, который вы запросили, в то время как readQuery позволяет вам читать данные только из корневого типа запроса.

Для этого вам понадобится id данных, возвращаемых функцией dataIdFromObject, как определено при инициализации ApolloClient. Если id не существует в кеше, readFragment вернет null. Если id существует, но не имеет поля, указанного в запросе фрагмента, будет выдана ошибка.

Магический аспект в том, что объект может быть откуда угодно - он может быть в магазине как одиночный объект, из списка или даже из мутации. Пока сервер GraphQL предоставил вам объект с формой фрагментов, вы можете прочитать его из кеша.

writeQuery и writeFragment

Вы также можете записывать любые данные в кеш. Обратите внимание: это изменит только данные в вашем локальном кеше, но не изменит данные на вашем сервере. Если перезагрузить, то изменения исчезнут.

Эти методы имеют ту же сигнатуру функции, что и аналоги readQuery и readFragment, за исключением того, что требуется передача дополнительной переменной data.

Любой подписчик на магазин Apollo Client увидит эти обновления и соответствующим образом отобразит пользовательский интерфейс.

Зачем использовать хранилище данных?

Обход кеша

Когда имеет смысл не использовать кеш для определенной операции, вы можете использовать в своем запросе network-only или no-cache fetchPolicy .

  • network-only по-прежнему сохраняет ответ в кэш для последующего использования, минуя чтение и форсируя сетевой запрос. Это необходимо для обеспечения согласованности данных с сервером, но это достигается за счет мгновенного ответа пользователю.
  • no-cache политика не читает и не записывает в кэш с ответом. Он всегда будет делать запрос к серверу через ваш сетевой интерфейс. В отличие от сетевой политики, он не будет записывать данные в кэш после завершения запроса.

FetchPolicy - это не только эти два варианта. Дополнительные сведения о fetchPolicy см. На странице https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-options-fetchPolicy.

Обновление после мутации

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

  • refetchQueries - это самый простой способ обновить кеш. С помощью refetchQueries вы можете указать один или несколько запросов, которые вы хотите запустить после завершения мутации, чтобы повторно выбрать части хранилища, которые могли быть затронуты мутацией.

Если вы вызываете refetchQueries с массивом строк, то Apollo Client будет искать ранее вызванные запросы, которые имеют те же имена, что и предоставленные строки, а затем повторно выбирают эти запросы с их текущими переменными. Вы также можете импортировать запросы для других компонентов, чтобы убедиться, что эти компоненты будут обновлены.

  • update позволяет вам вносить изменения в вашу модель данных в ответ на мутацию любым удобным для вас способом.

Обратите внимание, что есть целый набор технических проблем с обновлениями после мутации. Подробнее об оптимистичном пользовательском интерфейсе см. Https://www.apollographql.com/docs/react/features/optimistic-ui.html

Добавочная загрузка

Если вы хотите обрабатывать разбиение на страницы с бесконечной прокруткой или при загрузке дополнительных данных вместо того, чтобы отбрасывать список, просто добавьте недавно загруженные данные в список, уже находящийся в магазине, вы можете использовать fetchMore.

Метод fetchMore принимает карту переменных, которая будет отправлена ​​с новым запросом. Нам нужно передать смещение, чтобы не получить элементы, которые уже есть в магазине. Обратите внимание, что карта переменных объединяется с той, которая была указана для запроса, связанного с компонентом, поэтому, например, нет необходимости переходить ограничения после того, как они были установлены.

По умолчанию запрос fetchMore - это запрос, связанный с контейнером, но он также может принимать запрос с именем аргумента, который может быть документом GraphQL, содержащим запрос.

Директива @connection

Запросы с разбивкой на страницы - это тот же запрос, за исключением того, что при вызове fetchMore обновляется один и тот же ключ кеша. Поскольку поля, которые имеют дело с разбивкой на страницы, часто имеют некоторые дополнительные аргументы, такие как курсор или ограничение, мы хотим убедиться, что у нас есть чистый ключ кеша, который не включает эти аргументы.

Директива @connection, представленная в Apollo Client 1.6, помогает указать, что данные, возвращаемые из этого поля, должны храниться с указанным ключом, что упрощает добавление в список из-за результатов мутации или разбивки на страницы.

Если мы не используем директиву @connection в этом поле, наши функции обновления мутации должны будут воспроизвести точный набор аргументов, изначально переданных в это поле.

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

Мы также можем использовать необязательный аргумент filter директивы @connection, чтобы включить аргумент запроса type в ключ хранилища, что приводит к нескольким значениям хранилища, которые накапливают запросы из каждого типа фида.

Подробнее о директиве @connection читайте на https://www.apollographql.com/docs/react/features/pagination.html#connection-directive и https://www.apollographql.com/docs/react/advanced/ caching.html # директива-подключение

Кэш-перенаправления с cacheRedirects

В некоторых случаях запрос запрашивает данные, которые уже существуют в клиентском хранилище под другим ключом. Очень распространенный пример этого - когда ваш пользовательский интерфейс имеет представление списка и подробное представление, которые используют одни и те же данные.

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

Мы знаем, что данные, скорее всего, уже находятся в кеше клиента, но, поскольку они запрошены с другим запросом, Apollo Client этого не знает. Чтобы сообщить Apollo Client, где искать данные, мы можем определить настраиваемые преобразователи.

Примечание. Это также будет работать с пользовательскими методами dataIdFromObject, если вы используете тот же метод.

Примечание: getCacheKey передается внутри третьего аргумента преобразователю для генерации ключа объекта на основе его __typename и id.

Чтобы выяснить, что вы должны указать в свойстве __typename, выполните один из запросов в GraphiQL и получите поле __typename.

Сброс магазина

client.resetStore полностью сбрасывает кеш Apollo. Он также обновляет любые ваши активные запросы и является асинхронным.

Если вы хотите очистить магазин, но не хотите обновлять активные запросы, используйте client.clearStore() вместо client.resetStore().

Чтобы зарегистрировать функцию обратного вызова, которая будет выполняться после сброса хранилища, используйте client.onResetStore и передайте свой обратный вызов. Чтобы зарегистрировать несколько обратных вызовов, снова позвоните client.onResetStore. Все обратные вызовы помещаются в массив и выполняются одновременно.

Примечание. Если вы используете apollo-link-state для управления локальным состоянием и вызываете client.resetStore в любом месте приложения, используйтеclient.onResetStore для записи значений по умолчанию в кеш.

Вы также можете вызвать client.onResetStore из компонентов React. Это может быть полезно, если вы хотите принудительно выполнить повторную визуализацию пользовательского интерфейса после сброса хранилища.

Если вы хотите отменить подписку на обратные вызовы от client.resetStore, используйте возвращаемое значение client.onResetStore для своей функции отмены подписки.

Подробнее о кэшировании данных см. Https://www.apollographql.com/docs/react/advanced/caching.html