Это руководство с некоторыми из общих шаблонов доступа и управления хранилищем / кешем в 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