GraphQL — это новый способ получения данных с сервера, поддерживаемый Facebook. Это спецификация, в основном простая, которой необходимо следовать как на сервере, так и на клиенте, чтобы достичь целей соответствия данных, поддерживаемых схемой.

Relay — это расширение GraphQL, которое является попыткой внести ясность в другие практические аспекты управления данными на клиенте, особенно для приложений на основе React. Однако, будучи спецификацией, это не единственная вещь React.

Я пытаюсь перенести веб-приложение, полностью основанное на семантической модели, с умеренно сложным пользовательским интерфейсом и богатым конечными точками REST и adhoc на землю GraphQL-Relay-React.

Как я упоминал ранее, GraphQL как спецификация и эталонная реализация Facebook довольно просты. Более того, поскольку моя серверная часть представляет собой не что иное, как набор RDF, хранящихся в тройном хранилище, поддерживаемом семантической моделью на основе OWL, создание схемы GraphQL для клиента было не таким уж сложным.

Настоящая проблема возникает, когда появляется Relay.

Relay пытается упростить некоторые практические болевые точки разработки интерфейса, такие как поток данных между компонентами пользовательского интерфейса, управление состоянием/областью, как локальное, так и глобальное, разделение ответственности при извлечении данных с сервера, управление тайм-аутами и повторными попытками. И для этого требуется соглашение, а не подход к конфигурации. По дизайну он создан с учетом React (но нет причин, по которым его нельзя использовать без него).

В названии GraphQL есть термин query, и на то есть веская причина. Пока приложение запрашивает данные с сервера, все работает нормально. Но чтобы иметь хоть какую-то осмысленную реализацию, нам нужно записать некоторые данные. Или, как говорят в функциональном мире, нам нужны побочные эффекты. В мире GraphQL это называется Мутации.

Мутации — позднее добавление в спецификацию, и опять же достаточно простое. Это просто обязывает клиента сказать, что он хочет написать, а также упомянуть, как это изменит общую систему. т.е. для каждого запроса на мутацию существует объект полезной нагрузки, который клиенты должны использовать, чтобы попросить сервер GraphQL получить все, что, по их мнению, могло измениться из-за того, что они сделали. На уровне клиента это чем-то похоже на монадическую систему (правда, без обязательных законов), где общее состояние также является частью ввода и вывода.

Взгляд Relay на мутации все еще немного заржавел. Как на уровне спецификации, так и в текущей реализации. Сказав это, я вполне уверен в работе, которую выполняют коммиттеры в Facebook и другие организации.

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

Есть несколько важных дискуссий о мутациях, таких как проблемы Github и вопросы StackOverflow.

Я просто хочу повторить, что Relay (больше, чем GraphQL) нуждается в другом подходе к созданию клиент-серверных приложений. У меня наверняка будет больше, чтобы написать об этом (в гораздо меньших дозах, чем это), когда я буду углубляться в эту землю.

Вот несколько моих реализаций на данный момент

Идентификация объекта — важное понятие при работе с Relay-on-React (RoR). Почти во всех примерах Relay вход в приложение происходит путем извлечения коллекции определенного типа, что означает, что хранилище Relay получает информацию об идентификаторах отдельных экземпляров.

Эти идентификаторы, как указано в документации, являются непрозрачными, что, другими словами, является независимым от домена способом идентификации экземпляра как клиентом, так и сервером. Это синоним столбца идентификатора в базах данных (и SQL, и NOSQL), который отличается от специфичной для домена идентификации того же экземпляра.

Relay Store сохраняет эти идентификаторы как __dataID__ для каждого экземпляра, который он отслеживает, а затем использует один и тот же для всех своих упражнений по извлечению данных, например, когда какой-либо компонент React хочет получить дополнительную информацию об этом экземпляре или экземпляр изменяет состояние в результате некоторой мутации.

Если идентификатор экземпляра не будет соответствовать тому, что Relay сохраняет и что отправляет сервер, от Relay будут появляться странные предупреждения/сообщения об ошибках. Или Relay не будет создавать правильный запрос к серверу GraphQL. Что еще больше расстраивает, поскольку я потратил много времени на отладку своего приложения, а не на просмотр запроса, созданного Relay.

Способ, который сработал для меня, и я думаю, что при мышлении в Relay рекомендуется следующее:

  • ваши экземпляры всегда должны обрабатываться с уникальным идентификатором, который следует шаблону и отличается от идентификатора, специфичного для домена (если есть)
  • шаблон известен серверу, поэтому его можно расшифровать в функции разрешения вашего определения узла, а идентификатор домена используется для дальнейшей обработки.
  • Клиент ретрансляции не должен знать о шаблоне, чтобы разделение ответственности оставалось неизменным.
  • однако тот же идентификатор следует использовать всякий раз, когда клиенту ретрансляции необходимо идентифицировать экземпляр, например. в методе getConfigs класса Mutation или компоненте React, создающем фрагменты запроса для соответствующей информации того же экземпляра
  • Хранилище ретрансляции внутренне сопоставляет поле id типа Node (конкретный интерфейс ретрансляции для вашей схемы GraphQL) с __dataID__, а затем использует его для отслеживания одного и того же экземпляра через границы приложения. Нашему приложению не нужно заботиться о внутреннем представлении, но мы должны быть уверены, что идентификатор нашего экземпляра непротиворечив и доступен для хранилища Relay в любое время. Лучший способ проверить то же самое — через React Chrome Plugin, где мы можем увидеть, какие реквизиты имеют ретрансляторы данных.

Апис мутации на стороне клиента все еще развивается, и в будущих версиях реле появятся некоторые важные обновления. Одной из запутанных особенностей является конфигурация RANGE_ADD для мутатора Relay.

Если в результате мутации к существующему соединению добавляются некоторые новые ребра (способ Relay для представления графа ассоциаций между типами GraphQL, например, пользовательский тип имеет todos подключения для представления списка типов todo), мутация должна иметь connectionEdge как одно из выходных полей

то же самое преимущество затем можно использовать в функциях getFatQuery и getConfigs мутации, чтобы попросить ретрансляционное хранилище волшебным образом позаботиться о репликации той же операции сложения в своем хранилище, имитируя то, что произошло на стороне сервера. Это действительно мощная функция, но у нее все еще есть некоторые шероховатости, особенно когда она выдает странные предупреждения и молча терпит неудачу. Итак, вот что сработало для меня

Параметр RANGE_ADD для мутатора будет работать только для экземпляров, которые уже отслеживаются Relay. Другими словами, если рассматриваемое соединение ранее не опрашивалось каким-либо компонентом, то Relay пропустит его запрос, когда создаст окончательный запрос на мутацию, и покажет это странное предупреждение — ново созданное ребро ‹edge_name› и его ‹ поле node_name›. Вы забыли обновить конфигурацию мутации RANGE_ADD?.

Relay ищет общие поля только тогда, когда он пересекает то, что запрашивается в getFatQuery, и то, что именно нужно его компонентам в соответствии с их определением getFragments. Итак, проверьте, что соединение используется хотя бы в одном из фрагментов компонента.

В будущих обновлениях приведенное выше предупреждающее сообщение будет заменено соответствующим сообщением в зависимости от того, находится ли проблема на стороне клиента (т. е. когда соединение никогда не запрашивается до запроса как часть мутации) или на стороне сервера, когда сервер не включает новое преимущество как часть полезной нагрузки мутации. Ознакомьтесь с вопросом №542 для обсуждения и вопросом №574 для возможной реализации

В тех случаях, когда вам все еще нужно получить поля полезной нагрузки мутации, которые не запрашиваются ни одним компонентом, есть новая опция REQUIRED_CHILDREN, которая заставит Relay включить соответствующие поля в свой запрос мутации. Посмотреть выпуск №237

Постоянная ссылка на kaushikc.org