Интеграция GraphQL в наш стек React Native / Redux
GraphQL - это технология, созданная Facebook, по своей сути это язык запросов для API и среда выполнения для выполнения этих запросов с вашими существующими данными (цитируются с веб-сайта). Чтобы реализовать GraphQL, необходимо реализовать сервер, который предоставляет URL-адрес с путем /graphql
, в нашем случае мы использовали graphql-ruby
, что оказалось довольно простым и хорошо документированным.
Когда дело дошло до написания клиента для нашего приложения React Native, реализация была не такой простой, как на бэкэнде, это особенно актуально для нас, потому что у нас уже есть инструмент управления состоянием (Redux). У нас было 3 варианта:
- Продолжайте работать с GraphQL + Apollo и используйте реализацию кэширования и локального хранилища для сохранения пользовательских данных, связанных с этой частью приложения.
- Используйте react-apollo, чтобы обернуть компоненты, которые будут отвечать за создание мутаций или запросов, через их интерфейс компонентов высшего порядка (HOC), а затем передать это в кеш посредством диспетчеризации действий redux.
- Используйте автономную компонуемую сеть Apollos для подключения сетевых запросов GraphQL к нашему текущему сетевому стеку.
На данный момент первый вариант был бесполезен, поскольку у нас уже есть способ хранить данные локально, и работа над ним одновременно с тестированием GraphQL не казалась разумным выбором.
Мы начали с реализации второго, основанного на этой статье. Это работало довольно хорошо, но нам не хотелось, чтобы весь этот код выборки находился рядом с представлением. Поэтому мы решили поискать другой вариант, когда мы подошли к третьему варианту, реализации автономного составного сетевого плагина, который соответствует нашим текущим потребностям, и это то, что я собираюсь показать вам, как это сделать в этой публикации.
Наш сетевой стек
Сетевые запросы создают множество побочных эффектов для вашего программного обеспечения, по этой причине мы моделируем его с помощью redux-loop, где мы можем тщательно контролировать, какое поведение будет иметь все возможные побочные эффекты, которые может иметь этот запрос. В дополнение к этому, отсутствие кода, вызывающего побочные эффекты в нашем сетевом стеке, было целью, но сложной задачей для достижения, особенно когда нужно обмениваться данными между модулями / редукторами.
Чтобы попытаться убежать от этого кода, который генерирует побочные эффекты в нашем сетевом стеке, мы абстрагировали сетевой запрос на действия redux.
Учитывая, что у вас есть типы, действия, селекторы и редуктор:
Обратите внимание, что редуктор использует функцию mergeChildReducers
из redux-loop
. Мы используем это для обмена данными между модулями в нашем локальном состоянии, скажем, вы хотите иметь доступ к определенным данным, которые уже есть у другого редуктора, эта функция помогает объединить оба редуктора, чтобы у вас был доступ к данным, доступным на этом дочернем редукторе. .
Возвращаясь к запросу, можно увидеть REQUEST
сокращение, мы используем функцию loop
redux-loop, чтобы либо изменить / не изменять состояние, либо вернуть команду, которая запустит необходимую работу. Интересным фактом является то, что мы всегда возвращаем сокращения с помощью функции loop
, даже когда у нас нет команды для запуска, это делается для поддержания согласованности подписи, когда у нас нет команды для передачи, мы используйте redux-loop'sCmd.none
.
Команда сопоставляется с функцией, которая выполняет аутентифицированный сетевой запрос с использованием token
, это простая функция, которая форматирует запрос правильным способом для отправки и отображает ответы в желаемый формат.
Также обратите внимание на оба варианта функции Cmd.run
, successActionCreator
и failActionCreator
. Первый - это ловушка, которую нам пришлось реализовать, чтобы поддерживать возможности отладки во время путешествий, она отображается в файл с именем success-actions.js
, который представляет собой объединение всех response-callbacks.js
всех модулей, которые отправляют сетевые запросы. Второй, failActionCreator
, - это действие, которое отправляется в случае ошибки сетевого вызова, например, когда сервер вернул 500.
После того, как вы настроили сетевой модуль со всем необходимым кодом для получения действий, сделайте сетевой запрос и отправьте ответ на ответ действия success
. Вы можете создать необходимый код запроса / ответа на выбранном вами редукторе. Обратите внимание, что необходимо сопоставить success-callbacks.js
с success-actions.js
.
Написав сетевой стек таким образом, вы можете быть уверены, что все данные, которыми вы делитесь с вашим сетевым модулем, являются чистыми и будут обновлены, как только они будут обновлены / обновлены его локальным редуктором.
Что насчет GraphQL
Чтобы подключить GraphQL к этому, все, что нам нужно сделать, это заменить действие request
на действие graphqlOperation
.
Следуя тому же шаблону для действия запроса, мы можем абстрагировать составной сетевой интерфейс apollo и подключить его к нашему сетевому стеку, что позволяет нам не изменять большую часть наших текущих шаблонов кода.
После того, как вы настроили необходимые команды и сокращения, чтобы иметь возможность запускать сетевой запрос через GraphQL, отправляя действие redux. Вы должны реализовать необходимый код в редукторе, который хочет сделать Query
или Mutation
для сервера GraphQL.
В этом примере мы собираемся сделать мутацию, которая представляет пользователя, выполняющего регистрацию.
Обратите внимание, что нам нужно обновить сетевой файл success-actions.js
, чтобы это работало.
Когда пользователь запускает действие, которое должно привести к операции GraphQL, в данном случае мутации, действие будет сокращено и вызовет сетевое действие graphqlOperation
с полезной нагрузкой, необходимой для выполнения запроса на клиент graphql. Когда этот запрос возвращается с ответом, он сопоставляется с signupResponse
, который, в свою очередь, отображает полезную нагрузку в желаемый формат и отправляет ее редуктору, где полезная нагрузка будет сохранена в состоянии.
Заключение
Можно видеть, что GraphQL достаточно гибок, чтобы позволить вам подключить его прямо к вашей текущей инфраструктуре, принося вам все преимущества, которые он имеет, но без обратной стороны необходимости полностью изменять то, как вы делаете что-то в своем коде.
Обратной стороной такого подхода является то, что он добавляет немного больше стандартного кода, заставляя вас явно писать обратные вызовы действий в код. Кроме того, это делает вашу кодовую базу более сложной и дает больше инструментов для изучения и совершенствования.
Положительной стороной этого является то, что у вас есть доступ ко всей мощи Redux и GraphQL, что позволяет создавать увлекательный и сложный пользовательский интерфейс.
Надеюсь, это помогло вам пройти по пути Redux, React Native и GraphQL. Если у вас есть какие-либо вопросы или предложения, не стесняйтесь оставлять ответ.