Real-World Reactanational Apps облегчает реагирование в родных элементах, шумах и MOBX MST
Qaiser Abbas Real-World Reactanative Apps облегчает реагирование в реактивных элементах, шумах и MOBX MSTSource: pixabay.com в этом посте мы построим мобильное приложение реального мира в Reactanation. Мы также рассмотрим некоторые методы и библиотеки разработки, включая следующее: управление структурению каталога (в MOBX) в стиле кода
В этом посте мы построим мобильное приложение реального мира в реактивном родном. Мы также рассмотрим некоторые практики и библиотеки развития, в том числе следующие:
И важный, но часто игнорируемая часть: тестирование единиц вашего приложения (через Whest и фермент ).
Так что давайте начнем!
Управление государством в реакции
React и Reactanation сделали создание приложений для одиноких страниц и мобильных приложений и простого и простого, но они охватывают только вид приложений. Государственное управление и дизайн пользовательского интерфейса все еще могут быть болезненной частью построения приложения.
Для реагирования доступны несколько популярных государственных библиотек государственных библиотек. Я использовал redux, mobx и rxjs. Хотя все три из них хорошо по-своему, я наслаждался Mobx больше всего из-за своей простоты, элегантности и мощного государственного управления.
Redux Основываясь в основном на концепции функциональных программирований и чистых функций, пытается решить сложность управления государством, навязывая некоторые ограничения, когда возможны обновления. Эти ограничения отражены в трех основных принципах: единый источник правды, только для чтения и чистых функций. Вы можете прочитать больше о Эти принципы в документации Redux Отказ
Пока я фанат функционального программирования, я испытал, что приходится иметь дело с большим количеством ненужного кода котел при работе с Redux. Вы также должны написать код для диспетчеризации действий и преобразовывать состояние самостоятельно.
Mobx, с другой стороны, делает эту работу для вас, что облегчает обслуживание и веселее для работы. Вам нужна нужная сумма кода и ограничения в MOBX для достижения превосходного управления государством и хорошего опыта разработчика.
В Redux вам также приходится проводить значительное количество времени нормализации и отклонения ваших данных. В MOBX вам не нужно нормализовать данные, и MOBX автоматически отслеживает отношения между состоянием и деривациями. Мы пойдем в это позже.
RXJS Это библиотека реактивной программирования для JavaScript. Он отличается от Mobx в том, что RXJS позволяет вам реагировать на события во время в MOBX. Вы соблюдаете значения (или состояние), и это поможет вам реагировать на изменения в состоянии.
Хотя как RXJS и MOBX обеспечивают возможность выполнять реактивное программирование, они совершенно отличаются в своих подходах.
О нашем приложении
Приложение, которое мы будем строить, для книжного магазина. Он в основном состоит из двух простых просмотров: вид книг и вид авторов.
Приложение будет содержать навигационный ящик с двумя параметрами меню, позволяя пользователю переключаться между двумя представлениями. Первый вариант будет для навигации на просмотр книг, а другой вариант будет переходить к представлению авторов.
Взгляд книг будет содержать список книг, а также вкладка, позволяющая пользователю переключаться между художественными и нефинтирующими книгами. Вид авторов, содержащий список авторов.
Мы будем устанавливать все на Mac OS. Большинство команд будут одинаковыми, когда у вас установлен узел, но если вы сталкиваетесь с любыми проблемами, дайте мне знать, (или просто Google IT).
Темы охватывали
Мы охватим различные темы и различные библиотеки, необходимые для создания и тестирования полного взрывательного реагирования на новое применение:
Мы установим Create-raction-native-app и используйте его для загрузки нашего приложения книги
Настройка красивее, ESLINT и Руководство по стилю Airbnb для нашего проекта
Добавление ящика и вкладок навигация с использованием React-навигации
Проверьте наши реактивные компоненты с шумом и ферментом
Управляйте состоянием нашего приложения, используя MOBX (дерево MOBX-State). Это также включает в себя некоторые изменения пользовательских интерфейсов и больше навигации. Мы будем отказаться и фильтровать книги по жанру и позволить пользователю видеть экран детализации книги, когда пользовательские нажатия на книгу.
Вот демонстрация приложения Bookstore, которое мы собираемся построить:
Что мы не будем покрывать
Есть несколько вещей, которые мы не будем охватывать в этой статье, которую вы можете понадобиться в вашем проекте:
Инструменты для добавления системы статического типа в JavaScript, как поток и Машинопись
Несмотря на то, что мы добавим какой-то стиль в наше приложение, мы не будем подробно относиться к различным вариантам, доступным для добавления стилей в реактивном применении. Стильные компоненты Библиотека является одним из самых популярных как для реагирования, так и для реактивных применений.
Мы не будем строить отдельный бэкэнд для нашего приложения. Мы пройдем через интеграцию с API Google Books API, но мы будем использовать данные издевательства по большей части.
Создать реагировать нативное приложение с использованием CLI CLI (CRNA)
Создать реагировать нативное приложение это инструмент, созданный Facebook и Экспо Команда, которая делает его ветером, чтобы начать работу с реагированным нативным проектом. Мы инициализируем наше приложение Reactanation, используя КРНК CLI. Так что давайте начнем!
Предполагая, что у вас есть Узел Уже установлены, нам нужно установить Create-raction-native-app Во всем мире, так что мы можем инициализировать новый реагировать нативный проект для нашего книжного магазина.
npm install -g create-react-native-app
Теперь мы можем использовать CLI Create-React-And-App CLI для создания нашего нового реагирования нативный проект. Давайте назовем это Bookstore-App :
create-react-native-app bookstore-app
После того, как КРК выполняется загрузка нашего собственного применения реагирования, оно покажет некоторые полезные команды. Давайте изменим каталог на вновь созданное приложение CRNA и запустите его.
cd bookstore-app npm start
Это запускает Packager, дающий возможность запустить симулятор iOS или Android или открыть приложение на реальном устройстве.
Открытие приложения КРК на реальном устройстве через EXPO
Когда приложение запускается через NPM начать , QR-код будет отображаться в вашем терминале. Самый простой способ посмотреть на наше приложение для начинание, использует приложение EXPO. Сделать это:
Установите Экспо Клиентское приложение на вашем iOS или Android-устройстве.
Убедитесь, что вы подключены к той же беспроводной сети, что и ваш компьютер.
Используя приложение EXPO, сканируйте QR-код с вашего терминала, чтобы открыть свой проект.
Открытие приложения КРК в симуляторе
Чтобы запустить приложение на симуляторе iOS, вам нужно установить XCode. Чтобы запустить приложение на виртуальном устройстве Android, вам необходимо настроить среду разработки Android. Посмотрите на руководство по нанесению реагирования на работу как для установок.
Настройка красивее, ESLINT и стиль Airbnb
В этом разделе мы настроим надежнее руководство по стилю Airbnb, чтобы убедиться, что наш код не только выглядит довольно красиво, но и запускает подцинкт кода.
Зачем использовать линтальный инструмент?
JavaScript – это динамический язык, и не имеет системной системы статического типа, подобно таким языкам, как C ++ и Java. Из-за этой динамической природы JavaScript не хватает вида инструментов, доступных для статического анализа, который предлагает многие другие языки.
Это приводит к труднодоступным ошибкам, связанным с типами данных, и требует большего усилия в отладке и устранении неисправностей этих вопросов, особенно для неопытных разработчиков JavaScript.
Поскольку это не скомпилированный язык, ошибка обнаружены, когда код JavaScript выполняется во время выполнения. Есть такие инструменты, такие как TypeScript и Flow, которые помогают поймать эти ошибки, добавив систему статического типа на JavaScript, но мы не будем ни в одном из этих инструментов в этом руководстве.
С другой стороны, существуют линтные инструменты, такие как доступен Eslint, который выполняет статический анализ кода JavaScript на основе настраиваемых правил. Они выделяют проблемы в коде, который может быть потенциальными ошибками, которые помогают разработчикам обнаруживать проблемы в их коде, прежде чем оно выполняется.
Установка и настройка Eslint
Хороший подвижный инструмент чрезвычайно важен для того, чтобы качество запечено с самого начала, и ошибки находятся рано. Eslint также помогает вам реализовать руководящие принципы стиля.
Чтобы убедиться, что мы пишем высококачественный код и имеем правильные инструменты с самого начала нашего проекта «Книжный магазин», мы начнем наш учебник, сначала реализовавшиеся подвижными инструментами. Вы можете узнать больше о Eslint на их сайте Отказ
ESLINT полностью настраивается и настраивается. Вы можете установить ваши правила в соответствии с вашими предпочтениями. Однако различные конфигурации правил льмина были предоставлены сообществом. Одним из популярных из них является гид стиля AirBNB, и это тот, который мы будем использовать. Это будет включать правила Eslint Airbnb, включая ECMAScript 6+ и реагировать.
Во-первых, мы установим ESLINT, запустив эту команду в терминале:
Мы будем использовать Airbnb Eslint-config-airbnb Содержит правила ESLINT AIRBNB, включая ECMAScript 6+ и реагировать. Это требует определенных версий Eslint, Eslint-Plugin-Import, Eslint-Plugin-React и Eslint-Plugin-JSX-A11Y. Чтобы перечислить одноранговые зависимости и версий, запустите эту команду:
npm info "eslint-config-airbnb@latest" peerDependencies
Во время этого письма это версии, показанные на выходе из вышеуказанной команды:
Это установит необходимые зависимости и генерируют .eslintrc.js Файл в корневом каталоге проекта. Файл .eslintrc.js должен иметь следующие конфигурации:
module.exports = { "extends": "airbnb"};
Кодовый стайлинг
Хотя у нас есть подцинкт, покрытый ESLINT и руководством по стилю Airbnb, большая часть качества кода является последовательным стайлингом кода. Когда вы работаете над командой, вы хотите убедиться, что форматирование и отступ кода согласуются по всей команде. Красивее – это просто инструмент для этого. Он гарантирует, что весь код соответствует согласованному стилю.
Мы также добавим Плагин Eslint для Cretetier , который добавит красивее в качестве правила ESLINT и отчетности различий в качестве отдельных проблем Eslint.
Теперь между правилами ESLINT могут быть конфликты между правилами ESLINT и форматирование кода, сделанные красивее. К счастью, есть доступный плагин Eslint-Config-Crackier Это отключает все правила, которые не нужны или могут конфликтовать с красивее.
Установить и настроить красивее с помощью Eslint
Давайте установим все необходимые пакеты, красивее и Eslint-Plugin-stretier. Нам также нужно будет установить Eslint-config-airbnb для этого:
Примечание: Если ESLINT устанавливается по всему миру, то убедитесь, что Eslint-Plugin-Breettier также установлен глобально. Глобально установленная ESLINT не может найти локально установленный плагин.
Чтобы включить плагин Eslint-Plugin-Plugin, обновите файл .eslintrc.js, чтобы добавить «красивее» плагин. И показать ошибку отвлечения в более красивых правилах форматирования, добавьте «правило», чтобы показать ошибку на «красивее/красивее». Вот наш обновленный .eslintrc.js:
Eslint-Config-Crackier Также поставляются с инструментом CLI, чтобы помочь вам проверить, содержит ли ваша конфигурация любых правил, которые ненужны или конфликт с красивее. Давайте быть активным и сделаем это.
Во-первых, добавьте скрипт для него в Package.json:
Теперь запустите команду «Eslint-Check», чтобы увидеть противоречивые правила Eslint и Cretetier:
npm run eslint-check
Это перечисляет противоречивые правила в терминале. Отключим противоречивые правила, обновляя файл .eslintrc.js. Я также предпочитаю SingleQuote и TrailingComma, поэтому я также настрою эти правила. Это то, что наш файл .eslintrc.js выглядит так:
Если вы сейчас запустите Eslint с --fix Флаг, код будет автоматически отформатирован в соответствии с симпатичными стилями.
Настройте VS-код для запуска ESLINT на сохранении
Мы можем настроить любую IDE, чтобы автоматически запустить Eslint на Save или как мы вводите. Поскольку мы также сконфигурировали красивее вместе с Eslint, наш код автоматически претендует. VS Code – это IDE популярна в сообществе JavaScript, поэтому я покажу, как настроить Auto-Fix Eslint в Save с использованием VS Code, но этапы будут похожи на любой IDE.
Чтобы настроить VS-код для автоматического запуска ESLINT на сохранении, нам сначала необходимо установить расширение ESLINT. Перейдите к расширениям, ищите расширение «ESLINT» и установите его. Как только расширение ESLINT установлено, перейдите в Предпочтения> Пользователь Setti NGS, и установить «eslint.autofixSave» для True. Также убедитесь, что «файлы.autosave» либо устанавливаются на «выключенные», «OnfocusChange» или «OnWindowChange».
Теперь откройте файл App.js. Если ESLINT настроен правильно, вы должны увидеть некоторую ошибку льминания, например, «функция React/Pudes-Painter-Function», «React/JSX-FileName-Extension», а также ошибки «безрезультатно-определяют». Давайте перевернем эти «выключенные» в файле .eslintrc.js. Я также предпочитаю SingleQuote и TrailingComma, как я уже упоминал выше, поэтому я также настрою эти правила.
Я знаю, что это было много работы, учитывая, что мы даже не начали работать над нашим приложением! Но поверьте мне, эта настройка будет очень полезной для ваших проектов в долгосрочной перспективе, даже если вы команда одного человека. Когда вы работаете с другими разработчиками, стандарты льмина и программирования будут иметь большое значение в сокращении дефектов кода и обеспечения согласованности в стиле кода.
Вы можете найти изменения, сделанные в этом разделе в Эта ветка из учебного хранилища.
Ящик и вкладки навигация с использованием реактивных навигаций
В этом разделе мы добавим навигацию ящика и вкладок, используя React-навигацию.
Наше приложение Bookstore будет содержать навигационный ящик с двумя вариантами меню. Первый пункт меню для Автозерный экран , содержащий список авторов. Второй пункт меню для Книжный экран , содержащий список книг.
Нажатие на книгу возьмут пользователя на экран BookDetail. Для навигации между разными взглядами мы будем использовать Реагировать навигацию Чтобы добавить навигацию в наше приложение. Итак, давайте сначала установим его:
npm install --save react-navigation
CreatestackAvigator
Наше приложение Reactanation будет содержать два модуля:
Модуль автора, позволяющий пользователям просматривать список авторов
Модуль книг, содержащий список книг.
Авторские и книжные модули будут реализованы с помощью Stacknavigator из Реагировать навигацию Отказ Подумайте о Stacknavigator в качестве стека истории в веб-браузере. Когда пользователь нажимает на ссылку, URL нажата в стек истории браузера, и удаляется сверху стека истории, когда пользователь нажимает кнопку «Назад».
Для книг экрана и авторы экрана мы просто добавим два нестандартных Компоненты реагирования На данный момент с некоторыми кнопками для проверки нашей экранной навигации и функциональности ящика:
const BooksScreen = ({ navigation }) => ( )
const AuthorsScreen = ({ navigation }) => ( navigation.navigate('Books')} title="Go back to Books" />)
Навигация.opendRawer () заставит ящик для открытия. навигация .naviage () Позволяет приложению ориентироваться на разные экраны.
В нашем приложении мы добавим ящик, который будет поддерживать меню для наших модулей автора и книги. Мы реализуем ящик, используя React навигацию СоздатьRawernavigator Отказ
Первое меню в ящике будет для модуля автора, а второй для модуля книги. Автор и книга стеки навигаторов будут в главном Норваке.
Мы переименованы в экспорт по умолчанию в приложение
Мы добавили два компонента без природы для наших экранов, книг и авторы экрана.
Мы добавили стекнавигатор от Реагировать навигацию Для реализации навигации для нашего приложения.
Мы использовали СозданиеRawernavigator () от реагирования навигации по реализации навигации ящики. Это делает содержимое ящика наряду с пунктами меню для книг и авторов.
И после принятия вышеуказанных изменений вот как наш UI выглядит, когда мы нажимаем на кнопку «Открытый ящик» и навигация между экранами.
Структура каталогов
Важно подумать о вашем приложении и как вы будете структурировать свои файлы и ресурсы в начале проекта. Хотя существует несколько способов структурировать код вашего приложений, я предпочитаю определение файлов и тестов с использованием архитектуры на основе функций. Котактивные файлы, связанные с определенной функцией или модулем, имеют ряд преимуществ.
Давайте создадим каталог SRC, где мы сохраним все наши исходные файлы. Внутри его создайте два каталога: один для просмотра книги, названной «Книга», а другой для автора, названного «Автор».
Создайте файлы index.js в каждом из двух каталогов, которые мы только что добавили. Эти файлы будут экспортировать компоненты для каждого из наших представлений. Переместите код из App.js для компонентов BookView и Arrview в эти файлы и вместо этого импортируйте их.
Важно отметить, что рефакторинг должен быть большой частью рабочего процесса развития. Мы должны постоянно рефакторизовать наш код, чтобы подготовить себя к будущим изменениям и проблемам. Это оказывает большое влияние на производительность и управление изменениями в долгосрочной перспективе.
Наше приложение все еще должно работать, как раньше рефакторинга. Вот …| Файл разница наших недавних изменений Отказ
Каждый из экранов будет иметь заголовок, что означает, что мы будем дублировать один и тот же код вместе с стилями. Чтобы сохранить наш код сухим, давайте переместим название в отдельный файл SRC/Компоненты/title.js И повторно используйте, где это необходимо. Мы также переместим основные взгляды в новый родительский каталог SRC/просмотры держать их отдельными от других компонентов.
Вкладка навигация
Бизнес-требование для нашего приложения – иметь три вкладка в представлении книг, чтобы показать все книги по умолчанию и дополнительные вкладки для отображения фильтрованных книг для художественных книг и нефильтных книг. Давайте использовать Createbottomtabnavigator от реактивной навигации для реализации навигации вкладок.
import { createBottomTabNavigator } from 'react-navigation'
import { AllBooksTab, FictionBooksTab, NonfictionBooksTab } from ' components/book-type-tabs'
Мы также должны добавить заголовок на каждом экране, чтобы определить текущий выбранный экран. Давайте создадим отдельный каталог SRC/Компоненты Для всех общих компонентов и создайте файл для нашего Название Компонент внутри этого нового каталога.
// src/components/Title.jsimport React from 'react'import { StyleSheet, Text } from 'react-native'
Обратите внимание, что мы также добавили Стиль к XT> Компонент, импорт Оба стила oshee т.н D текст от реагирования- родной.
Мы добавим Название К каждому компоненту просмотра, предоставляя название текст в реквизитах. Также, поскольку авторы просмотра только что содержит список авторов, нам не нужен стекнавигатор для него, поэтому мы изменим его на обычный компонент реагирования. Вот что наше SRC/Просмотры/Автор/index.js Файл выглядит так:
Теперь, когда мы открываем меню книг из ящика, мы можем переключить вкладки, нажав на вкладки внизу.
С этими изменениями у нас есть наши навигации нашего приложения. Вот …| Развернуть для наших недавних изменений Отказ
Реагировать родные элементы
Существует несколько библиотек компонентов пользовательского интерфейса для добавления реактивных компонентов в стиле. Некоторые из более популярных – Реагировать родные элементы Натуральная база и Зажечь Отказ Мы будем использовать React Native Elements для нашего приложения Bookstore. Итак, давайте сначала установте реагирующие элементы:
npm install --save react-native-elements
Создание наших авторов списка с использованием реактивных элементов
Давайте использовать ListiTem Компонент из реагирования собственных элементов для добавления списка авторов на нашем экране автора.
Для списка авторов мы будем использовать данные и код из ListiTem демонстрация Мы пересмотрим ListiTem в более подробно, когда мы реализуем экран списка книги.
Вот …| Развернуть для наших недавних изменений Отказ
Тестирование реагирует родные компоненты с шумом и ферментом
В этом разделе мы добавим некоторые модульные тесты с помощью шума и фермента.
Настройка шума и фермента
Наличие модульных тестов для вашего кода действительно важно, чтобы вы могли уверены в своем коде, когда вы хотите что-то изменить. Это действительно окупается, когда вы добавляете больше функций, и вы можете внести изменения без страха за нарушение некоторых существующих функций вашего приложения в результате изменения. Вы знаете, что ваши тесты подразделений предоставляют безопасность для вашего приложения от утечки любых дефектов в производство.
Мы будем использовать jest в качестве нашей структуры тестирования вместе с утилитой тестирования JavaScript Airbnb Фермент Отказ Enzyme имеет гибкий и интуитивно понятный интерфейс, который делает его очень легко утверждать, манипулировать и комментариями по производству реагирования.
Комплект Create-React-And-App App уже включает в себя все связанные с этим связанные дневники и конфигурации. Работать с ферментом, нам нужно установить фермент и некоторые связанные зависимости. Так как мы используем Rect 16, мы будем добавлять React-Dom @ 16 и Фермент-адаптер-реагирование-16 Отказ
Нам нужно настроить Фермент-адаптер-реагирование-16 Отказ Мы сделаем это во время перспективы. Создать jestsetup.js Корень файла проекта, со следующим кодом:
import { configure } from 'enzyme'import Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
Теперь добавьте этот файл в конфигурацию jest в Package.json :
Тесты фермента и моментальных снимков для нашего заголовка компонента
Теперь мы все настроены на добавление ферментных испытаний. Я предпочитаю, чтобы тестировать совместно с моим кодом. Давайте создадим простой тест для нашего заголовка компонента, добавив тестовый файл рядом с нашим заголовочным компонентом. В этом тесте мы просто неглуемся визуализируйте заголовочный компонент, создаете снимок и проверьте стили компонентов. Создать файл SRC/Компоненты/__ Тесты __/title.js с следующим содержанием:
import React from 'react'import { shallow } from 'enzyme'import Title from '../Title'
Тесты должны проходить и генерировать снимок, давая следующий выход:
В случае, если вы не знакомы с помощью Jest Snapshot Testing, это отличный способ протестировать компоненты реагирования или различные виды выходов в целом.
В основном, Tomatchsnapshot () Вызов оказывает вашу компонент и создает снимок в __snapshots__ каталог (если снимок уже не существует). После этого каждый раз, когда вы повторно запустите свои тесты, шума будет сравнивать вывод визуализированного компонента с помощью снимка снимка, и потерпит неудачу, если будет несоответствие. Это покажет разницу между ожидаемым и фактическим выходом. Затем вы можете просмотреть различия, и если эта разница действительна из-за некоторых изменений, которые вы реализовали, вы можете повторно запустить тесты с помощью -у Флаг, который сигнализирует, чтобы обновить снимок с новыми обновлениями.
Если вы открываете файл снимка ( SRC/компоненты/__ тесты __/__ снимки __/title.js.snap ), вы заметите, что содержимое не очень читается. Это запутано кодом из ферментных обертков, поскольку мы используем фермент для оказания нашего компонента. К счастью, есть фермент-к-JSON Доступна библиотека, которая преобразует обертки фермента в формат, совместимый с помощью перспективного тестирования снимка.
Давайте установим фермент-к-JSON:
npm install -D enzyme-to-json
И добавьте его в настроенные конфигурации в качестве сериализатора Snapshot в Package.json :
Поскольку теперь мы ожидаем, что снимок отличается от предыдущего снимка, мы пройдем -у Флаг, чтобы обновить снимок:
npm test -- -u
Если вы снова открываете файл Snapshot, вы увидите, что снимок для компонента визуализации является правильным.
Мы больше погрузимся в перспективе тестирования в более поздних разделах.
Управление состоянием с навигацией навигации и MOBX
Mobx или Redux для государственного управления
Хотя React отлично подходит для управления видом на ваше приложение, вам вообще нужны инструменты для управления магазином вашего приложения. Как правило, я говорю, потому что вам не понадобится государственная библиотека управления вообще – все зависит от типа приложения, который вы строите.
Там есть несколько государственных библиотек по управлению, но самые популярные являются redux и mobx. Мы будем использовать MobX Store для нашего приложения Bookstore.
Я обычно предпочитаю Mobx Redux для управления магазином, потому что я чувствую, что требуется намного больше времени, чтобы добавить новые данные магазина в Redux по сравнению с MobX.
Некоторые недостатки в Redux:
Вам нужно добавить много кода Boeterplate.
Вы должны написать код для диспетчеризации действий и преобразовывать состояние самостоятельно.
Это заставляет вас реализовывать вещи определенным образом. Хотя это было бы хорошей в некоторых приложениях, я считаю, что количество времени, которое требуется, возможно, не стоит того, чтобы многие приложения.
Некоторые преимущества Mobx:
Он добавляет эту котующую таблицу для вас и делает это хорошо. Я считаю, что это очень легко работать, будь то начальная настройка или добавление дополнительной функциональности.
Это не заставляет вас реализовать ваши данные по течению определенным образом, и у вас гораздо больше свободы. Но опять же, это может быть более проблематичным, чем полезным, если вы не настроите свои магазины MobX правильно ..
Я знаю, что это чувствительная тема, и я не хочу начать обсуждение здесь, поэтому я оставлю эту тему на другой день. Но если вы хотите более перспективы на этом, есть НесколькоПерспективы На эту дискуссию по Интернету. Redux и Mobx – это отличные инструменты для управления магазином.
Мы будем постепенно добавлять функциональные возможности в наш магазин вместо того, чтобы добавить его все сразу, просто чтобы показать вам, насколько легко добавить больше возможностей для магазинов Mobx.
Mobx State Tree
Мы не будем использовать FOBX напрямую, но обертка на Mobx называется Mobx-State-Tree Отказ Они сделали прекрасную работу по описанию себя, поэтому я просто цитирую их здесь:
Мы будем использовать API Google Books, чтобы извлечь книги для нашего приложения. Если вы хотите следовать, вам придется создать проект в консоли Google Developers, включите API Google книги на нем и создать ключ API в проекте. Как только у вас есть ключ API, создайте файл Keys.json В корне проекта, со следующим контентом (заменить your_google_books_api_key с ключом вашей API):
{ "GBOOKS_KEY": "YOUR_GOOGLE_BOOKS_API_KEY"}
Примечание : Если вы не хотите проходить через этот процесс получения ключа API, не волнуйтесь. Мы не будем использовать Google API напрямую, и вместо этого выдемлете данные.
Google книги API конечная точка Книги/V1/Объемы Возвращает массив Предметы где каждый элемент содержит информацию о конкретной книге. Вот отрезанная версия книги:
{ kind: "books#volume", id: "r_YQVeefU28C", etag: "HeC4avg1XlM", selfLink: "https://www.googleapis.com/books/v1/volumes/r_YQVeefU28C", volumeInfo: { title: "Breaking Everyday Addictions", subtitle: "Finding Freedom from the Things That Trip Us Up", authors: [ "David Hawkins" ], publisher: "Harvest House Publishers", publishedDate: "2008-07-01", description: "Addiction is a rapidly growing problem among Christians and non-Christians alike. Even socially acceptable behaviors, ...", pageCount: 256, printType: "BOOK", categories: [ "Addicts" ], imageLinks: { smallThumbnail: "http://books.google.com/books/content?id=r_YQVeefU28C", thumbnail: "http://books.google.com/books/content?id=r_YQVeefU28C&printsec=frontcover" }, language: "en", previewLink: "http://books.google.com.au/books?id=r_YQVeefU28C&printsec=frontcover", infoLink: "https://play.google.com/store/books/details?id=r_YQVeefU28C&source=gbs_api", canonicalVolumeLink: "https://market.android.com/details?id=book-r_YQVeefU28C" }}
Мы не будем использовать все поля, возвращенные в ответ API. Итак, мы создадим нашу модель MST только для данных, которые нам нужны в нашем реактивном приложении. Давайте определим нашу книгу модель в MST.
Создать новую структуру каталогов Магазины/книга внутри SRC и создайте новый файл index.js внутри него:
// src/stores/book/index.jsimport { types as t } from 'mobx-state-tree'
В определении вышеуказанного узла MST наше Книга Тип модели определяет форму нашего узла – типа Книга – в на дереве штата Mobx. Типы. Model Тип в MST используется для описания формы объекта. Давая модель
Второй аргумент, аргумент свойств, представляет собой пару клавиша, где ключ – это имя свойства, а значение является его типом. В нашей модели ID это Идентификатор , Название имеет тип строка , PageCount имеет тип Номер , Авторы это Массив строк , Жанр имеет тип строка , Insocock типа логический и изображение типа строка Отказ
Все данные требуются по умолчанию для создания действительного узла в дереве, поэтому, если мы попытались вставить узл без заголовка, MST не позволит ему, и выбросит ошибку.
Жанр будет сопоставлен на Категории Поле (первое индексное значение массива категорий) данных API книг Google. Это может или не может быть там в ответ. Поэтому мы сделали его типа Может быть Отказ Если данные для Жанр не там в ответ, Жанр будет установлен на null в MST, но если это там, это должно быть типа строка для этого, чтобы быть действительным.
С Insocock Это наше собственное поле, и не возвращается в ответ от API Google Books, мы сделали его необязательно и дали ему значение по умолчанию. Мы могли бы просто назначить это значение правда Поскольку для примитивных типов MST может выводить тип из значения по умолчанию. Итак, Insocock: True такой же, как Instock: T.optional (T.Boolean, True) Отказ
Создание моделей Раздел Mobx-State-Tree Документация входит в подробности о создании моделей в MST.
Деревья MST защищены по умолчанию. Это означает, что только действия MST могут изменить состояние дерева.
Мы определили два действия: ОБНОВЛЕНИЕ книг это функция, которая называется только Лэйтные книги Функция, поэтому мы не подвергаем его внешнему миру. Лэйтные книги С другой стороны, выставлен (мы возвращаем его) и можно вызвать извне Книжный магазин Отказ
Асинхронные действия в MST написаны с использованием генераторов и всегда возвращают обещание. В нашем случае Лэйтные книги Нужно быть асинхронным, так как мы вызовите Ajax Call для API Google Books.
Мы будем поддерживать единственный экземпляр Книжный магазин Отказ Если магазин уже существует, мы вернем существующий магазин. Если нет, мы создадим один и вернемся в новый магазин:
// src/stores/book/index.jslet store = null
export default () => { if (store) return store
store = BookStore.create({ books: {} }) return store}
Использование магазина MST на наш взгляд
Начнем с точки зрения всех книг. Для этого мы создадим новый файл, содержащий наш BookListView составная часть:
import React, { Component } from 'react'import { observer } from 'mobx-react'import BookStore from '../../../stores/book'import BookList from './BookList'
Как вы можете видеть, мы инициализируем Книжный магазин в ComponentWillmount , а затем звонить Loadbooks () Чтобы извлечь книги из книг Google API асинхронно. Книжный блок Компонент, итерат над Книги Массив внутри Книжный магазин и делает Книга Компонент для каждой книги. Теперь нам просто нужно добавить это BookListView Компонент к AllbookStab Отказ
Если вы начнете приложение сейчас, вы увидите, что книги загружаются, как ожидалось.
Обратите внимание, что я использую CASCAL TAMING PACKING для файла, который возвращает один компонент RACT React в качестве экспорта по умолчанию. Для всего остального я использую корпус Kebab. Вы можете решить выбрать другую конвенцию именования для вашего проекта.
Если вы запустите NPM начать Теперь вы должны увидеть список книг, выходящих в Google API.
Вот …| Развернуть для наших изменений до сих пор Отказ
Добавление испытаний на наш книжный магазин MST
Давайте добавим некоторые модульные тесты для нашего книжного магазина. Однако наш магазин разговаривает с нашим API, который называет Google API. Мы можем добавить интеграционные тесты для нашего магазина, но добавить тесты подразделения, нам нужно как-то издеваться на API.
Простой способ издеваться на API – использовать Jest Manual Mocks Создавая __mocks__ каталог рядом с нашим существующим API.JS файл. Внутри его создайте еще один API.JS издевалась версия наших вызовов наших вызовов API. Тогда мы просто называем jest.mock ('..//API') В нашем тесте использовать эту издеванную версию.
Инъекция зависимостей в дереве штата Mobx
Мы не будем использовать Jest Manual Mocks. Я хотел бы показать вам еще одну функцию в MST, и продемонстрировать, насколько легко поднять наш API, используя MST. Мы будем использовать инъекцию зависимостей в дереве MOBX State, чтобы обеспечить простой способ издеваться на вызовы API, что делает наш магазин простым для тестирования. Обратите внимание, что наше хранилище MST также можно проверить без впрыска зависимостей с использованием шума-издевателей, но мы делаем это таким образом для демонстрации.
Можно вводить данные, специфичные для окружающей среды в дереве состояния, передавая объект в качестве второго аргумента для Bookstore.create () вызов. Этот объект будет доступен любой моделью в дереве, позвонив Генс () Отказ Мы будем вводить макет API в нашем книжном магазине, поэтому давайте сначала добавим дополнительную API Параметр к экспорту по умолчанию, и установите его на фактический Bookapi по умолчанию.
// src/stores/book/index.jslet store = null
export default () => { if (store) return store
store = BookStore.create({ books: {} }) return store}
Теперь добавьте MST View Для введенных API, схватив его, используя Генс () Отказ Затем используйте его в Лэйтные книги Функция как Self.api.fethetchbook () :
Я добавил задержку в ответ, чтобы ответ не был немедленно отправлен. Я также создал файл JSON с некоторыми данными, аналогичными для ответа, отправленного в Google Books API SRC/Stores/Book/Mock-API/Books.json
Теперь мы готовы ввести макет API в наши тесты. Создайте новый тестовый файл для нашего магазина со следующим контентом:
// src/stores/book/__tests__/index.jsimport { BookStore } from '../index'import api from '../mock-api/api'
it('bookstore fetches data', async () => { const store = BookStore.create({ books: [] }, { api }) await store.loadBooks() expect(store.books.length).toBe(10)})
Запустите тест магазина:
npm test src/stores/book/__tests__/index.js
Вы должны увидеть тестовый проход.
Добавление фильтра книг и применение TDD
Я верю в гибридный подход к тестируемому развитию. По моему опыту он работает лучше всего, если вы добавите некоторые основные функциональные возможности сначала при запуске проекта или при добавлении нового модуля или основной функциональности с нуля. Как только основная установка и структура реализована, то TDD работает очень хорошо.
Но я верю, что TDD – лучший способ приблизиться к проблемным пространством в коде. Это не только заставляет вас иметь лучшее качество и дизайн кода, но также гарантирует, что у вас есть тесты атомной единицы. Кроме того, он гарантирует, что ваши модульные тесты более сосредоточены на тестировании определенных функциональных возможностей, а не начисляющие слишком много утверждений в тесте.
Прежде чем мы начнем добавлять наши тесты и внесение изменений в наш магазин, я изменим задержку в нашем Mock API до 300 миллисец, чтобы убедиться, что наши тесты проходят быстрее.
Мы хотим Фильтр поле в нашем Книжный магазин модель и а setgenre () Действие в нашем магазине для изменения значения этого Фильтр Отказ
it(`filter is set when setGenre() is called with a valid filter value`, async () => { store.setGenre('Nonfiction') expect(store.filter).toBe('Nonfiction')})
Мы хотим запустить тесты только для нашего книжного магазина и сохранять тесты, работающие и просмотренные для изменений. Они будут запускаться, когда код был изменен. Таким образом, мы будем использовать команду Watch и использовать сопоставление шаблона пути к файлу:
npm test stores/book -- --watch
Вышеуказанный тест должен потерпеть неудачу, потому что мы еще не написали код, чтобы сделать тестовый проход. То, как работает TDD, заключается в том, что вы пишете атомный тест для проверки наименьшего единицы бизнес-требований. Затем вы добавляете код, чтобы сделать только этот тестовый проход. Вы проходите к тому же процессу итеративно, пока не добавим все бизнес-требования. Чтобы пройти наш тест, нам придется добавить Фильтр Поле типа Enum в нашем Книжный магазин модель:
И добавьте действие MST, которое позволит нам изменить значение фильтра:
const setGenre = genre => { self.filter = genre}
return { //... setGenre,}
С этими двумя изменениями мы должны быть в зеленом. Давайте также добавим отрицательный тест для неверного значения фильтра:
it(`filter is NOT set when setGenre() is called with an invalid filter value`, async () => { expect(() => store.setGenre('Adventure')).toThrow()})
И этот тест должен также пройти. Это потому, что мы используем тип enum в нашем магазине MST, а только допустимые значения Все , Фикция и Любовный Отказ
Первое значение индекса в Категории Поле данных издевательства классифицирует книгу как Фикция или Любовный Отказ Мы будем использовать его для фильтрации книг для наших Фикция и Любовный вкладки соответственно.
Мы также хотим, чтобы наши книги всегда были отсортированы по названию. Давайте добавим тест на это:
Давайте сначала добавим тест для сортировки книг:
it(`Books are sorted by title`, async () => { const books = store.sortedBooks expect(books[0].title).toBe('By The Book') expect(books[1].title).toBe('Jane Eyre')})
Чтобы сделать наш тестовый проход, мы добавим представление с именем Сортировка книг в нашем Книжный магазин модель:
get sortedBooks() { return self.books.sort(sortFn)},
И с этим изменением мы снова должны быть в зеленом.
Около мСТ видов
Мы только что добавили Сортировка книг Вид в нашу Книжный магазин модель. Чтобы понять, как MST мнения работают, нам придется понять MOBX. Ключевая концепция за MOBX: все, что может быть получено из состояния приложения, должно быть получено автоматически.
Вычисленные значения должны быть чистыми функциями, а с точки зрения в зависимости от наблюдаемых значений или других вычисленных значений они не должны иметь побочных эффектов. Вычисленные свойства лениво оцениваются, и их значение оценивается только тогда, когда их стоимость запрашивается. Вычисленные значения также кэшируются в MOBX, и это кэшированное значение возвращается при доступе этого вычисленного свойства. Когда в любом из наблюдаемых используемых в нем используется изменения, вычисляемое свойство пересматривается.
MST просмотры получены из текущего наблюдаемого состояния. Представления могут быть с или без аргументов. Виды без аргументов в основном Вычисленные значения От MOBX, определенного с использованием функций Getter. Когда наблюдаемое значение изменяется с действий MST, затронутое представление воспроизводится, вызвав изменение (реакция) в @observer составные части.
Добавление тестов на жанровый фильтр
Мы знаем, что в данных издевателях в Mock насчитывается семь научных книг. Давайте теперь добавим тест на фильтрацию по Жанр :
it(`Books are sorted by title`, async () => { store.setGenre('Nonfiction') const books = store.sortedBooks expect(books.length).toBe(7)})
Чтобы сделать фильтрацию по жандовой работе, мы добавим Жанр Поле строкового типа в нашем Книга Модель и сопоставьте ее к VomightInfo.Категории [0] получил от ответа API. Мы также изменим Сортировка книг Посмотреть дому до нашего Книжный магазин Модель для фильтрации книг перед сортировкой:
Примечание Отсюда, мы будем использовать данные издевания для наших фактических вызовов API вместо того, чтобы сделать запросы AJAX на API Google Books. Для этого я изменил Bookapi В Магазины/Книга/index.js Чтобы указать на MOD API ( ./mock-api/api.js ).
Обратите внимание, что дисплей для всех трех вкладок («все», «Художественная литература» и «Любостроение») похоже. Макет и формат элементов будут одинаковыми, но единственное отличие – это данные, которые они будут отображаться. И поскольку MOBX позволяет нам сохранять наши данные полностью отдельными с вида, мы можем избавиться от трех отдельных представлений и использовать тот же компонент для всех трех вкладок.
Это означает, что нам больше не нужны три отдельных вкладка. Итак, мы удалим Книга-Тип-Tabs.js Файл и используйте BookListView Компонент прямо в нашем Табнавигатор для всех трех вкладок. Мы будем использовать Tabbaronpress Обратный вызов, чтобы вызвать звонок на setgenre () в нашем Книжный магазин Отказ rult Diname , доступно на объекте навигационного состояния, передается в setgenre () Чтобы обновить фильтр, когда пользователь нажимает вкладку.
Обратите внимание, что мы упаковываем Createbottomtabnavigator в Mobx наблюдатель Отказ Это то, что преобразует класс React Component или автономной функции рендеринга в реактивный компонент. В нашем случае мы хотим фильтр в нашем книжном магазине, чтобы измениться, когда Tabbaronpress называется.
Мы также изменим представление, чтобы получить сортировочные книги вместо книг.
Наш список книг просто перечисляет имя и автор каждой книги, но мы еще не добавили ни одного стиля. Давайте сделаем это, используя ListiTem Компонент из Реагистрационные элементы Отказ Это простое изменение:
// src/views/book/components/Book.js
import { ListItem } from 'react-native-elements'
export default observer(({ book }) => ( ))
И вот как наш взгляд выглядит сейчас:
! [Книжный список с React – Nature-Elements.png] (.
Мы добавим поле Выбранный книг нашему Книжный магазин который будет указывать на выбранную модель книги.
selectedBook: t.maybe(t.reference(Book))
Мы используем ссылку MST для нашего Выбранный книг наблюдаемый. Ссылки в магазинах MST Убедитесь, что можно легко сделать ссылки на данные и взаимодействовать с ним, сохраняя данные, нормированные на заднем плане.
Мы также добавим действие, чтобы изменить эту ссылку:
const selectBook = book => { self.selectedBook = book}
Когда пользователь нажал на книгу в BookListView , мы хотим ориентироваться на пользователя к BookDetail экран. Итак, мы создадим ShowBookDetail Функция для этого и пропустите его как опоры для дочерних компонентов:
// src/views/book/components/BookListView.jsconst showBookDetail = book => { this.store.selectBook(book) this.props.navigation.navigate('BookDetail')}
В Книга Компонент, мы называем вышеуказанным ShowBookDetail Функция на onpress Мероприятие в книге ListiTem :
// src/views/book/components/Book.js
onPress={() => showBookDetail(book)}
Давайте теперь создадим BookDetailView Это будет отображено, когда пользователь нажимает книгу:
// src/views/book/components/BookDetailView.js
export default observer(() => { const store = BkStore() const book = store.selectedBook
Ранее у нас были только вкладки, но теперь мы хотим показать детали, когда пользовательские нажатия на книгу. Итак, мы экспортируем CreatestackActavigator вместо экспорта Createbottomtabnavigator напрямую. CreatestackActavigator будет иметь два экрана на стеке, Книжный блок и BookDetail экран:
Обратите внимание, что у нас есть вид списка и подробное представление внутри CreatestackActavigator Отказ Это потому, что мы хотим поделиться тем же BookDetailView только с разным контентом (отфильтрованные книги). Если мы хотели разные подробные представления, чтобы показать с разных вкладок, то мы создали бы два отдельных степнавигатора и включали их внутри табнавигатора. Что-то вроде этого:
Наши накладки нашей вкладки выглядят немного маленькими, и ударяют нижнюю часть экрана. Давайте починить это, увеличивая fontsize и добавление некоторых прокладка :
Давайте запустим наше приложение, нажмите на книгу, и экран детализации книги должен отображаться с деталями книги. Вот репо нашего готового приложения.
Спасибо за чтение!
И это завершает наш учебник по созданию реактивного применения с помощью магазина MOBX. Я надеюсь, что вам понравился пост и нашел это полезным.