Интеграция GraphQL в наш стек React Native / Redux

GraphQL - это технология, созданная Facebook, по своей сути это язык запросов для API и среда выполнения для выполнения этих запросов с вашими существующими данными (цитируются с веб-сайта). Чтобы реализовать GraphQL, необходимо реализовать сервер, который предоставляет URL-адрес с путем /graphql, в нашем случае мы использовали graphql-ruby, что оказалось довольно простым и хорошо документированным.

Когда дело дошло до написания клиента для нашего приложения React Native, реализация была не такой простой, как на бэкэнде, это особенно актуально для нас, потому что у нас уже есть инструмент управления состоянием (Redux). У нас было 3 варианта:

  1. Продолжайте работать с GraphQL + Apollo и используйте реализацию кэширования и локального хранилища для сохранения пользовательских данных, связанных с этой частью приложения.
  2. Используйте react-apollo, чтобы обернуть компоненты, которые будут отвечать за создание мутаций или запросов, через их интерфейс компонентов высшего порядка (HOC), а затем передать это в кеш посредством диспетчеризации действий redux.
  3. Используйте автономную компонуемую сеть 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. Если у вас есть какие-либо вопросы или предложения, не стесняйтесь оставлять ответ.