React Native: путь новичка

"Если долго сидеть на берегу реки,
можно увидеть,
как проплывает труп фреймворка,
который вы давно хотели изучить."
Китайская народная мудрость

Краткое содержание статьи:

1. Источники информации
2. React модули
3. React Native модули
4. JavaScript библиотеки
5. "Баги"
6. Выводы

React Native - самая, пожалуй, интересная и быстроразвивающаяся платформа. Сегодня ты создаешь новый проект на базе её последней версии, и уже через несколько месяцев она успевает устареть на несколько релизов. И если ещё год назад React Native был еще достаточно сырым продуктом, то уже сейчас к нем написано множество как плагинов для работы с нативными компонентами, так и обычных react-компонент.

Итак, с чего начать?


Могу порекомендовать книгу "Learning React Native: Building Native Mobile Apps with JavaScript" Bonnie Eisenman. Несмотря на то, что примеры из книги написаны с использованием устаревшего синтаксиса, её прекрасно можно использовать как пособие по изучению базовых принципов построения приложений на react-native. Книга рассматривает весь процесс создания приложения, вплоть до деплоя в стор c разбором отдельных компонент: как и зачем их использовать. Примеры же отлично укрепят полученные знания, так как копипастить тут не получится и нужно будет, переосмысливая, переписывать их на новый лад.

Далее по важности: документация. Здесь прекрасно то, что она актуальна. Все новинки релизов описаны. Все устаревшие методы указаны.
Выбираем вкладку "Building Projects with Native Code" и понеслась!..

Ну и далеко не последняя пристань react-native разработчика: http://stackoverflow.com/

Далее определимся с набором инструментов для react.


Хотелось бы отметить наиболее значимые и используемые модули:
  1. redux
    • react-redux
    • redux-logger - незаменимый инструмент при отладке
    • redux-saga - лучшее решение для организации сайд-эффектов

  2. селекторы
    • reselect - выбор данных из состояния приложения и компоновка их в нужную структуру. Удобно вынести эту логику из редьюсеров и вьюх в специальное место.
  3. jest - тестирование, идет из коробки. Главное - не пренебрегать и писать тесты =)
  4. eslint - инструмент для унификации стиля написания кода, а также выявления глупых и/или синстаксических ошибок.

Полезности RN


Ещё не могу не упомянуть об уже существующих библиотеках для react-native, которые несомненно упростят жизнь разработчику дабы не изобретать велосипед:

По работе с камерой и библиотекой фото и видео, загрузкой и шаринге есть неплохая статья на medium. А так же следующие библиотеки:


Последние три требуют дополнительных разрешений на телефоне, таких как: доступ к библиотеке, камере, локальному хранилище данных. Нужно отметить, что эти разрешения автоматически будут запрашиваться у пользователя при установке приложения. Исключение составляют новые (выше 6-ой) версии Андроида. Поэтому их нужно запрашивать во время обращения к нужным службам приложения (и вот почему). В документации есть пример, который можно оформить в виде небольшой библиотеки:

import { PermissionsAndroid, Platform } from 'react-native'

export const requestExternalStoragePermission = async (onSuccess, onError) => {
  // only for Android 6 and greater
  if ((Platform.OS === 'android') && (Platform.Version > 22)) {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
        {
          title: 'App read external storage Permission',
          message: `App needs access to your external storage
                    so you can take keep your data.`
        }
      )
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        onSuccess()
      } else {
        onError()
      }
    } catch (err) {
      console.warn(err)
    }
  } else {
    onSuccess()
  }
}

Здесь можно хранить запросы и на доступ к микрофону и камере.

Как вы, наверно, уже заметили в примере выше используется модуль Platform, который позволяет задавать специфичные для различных платформ вещи. Самым простым и распространенным примером будет задание высоты системной шапки:

Андроид (пример приложения фейсбука):

iPhone (пример приложения фейсбука):


Дело в том, что при вычислении высоты экрана берется фактическая высота устройства, но реальная область, доступная для приложения для Андроида, будет меньше на высоту этой самой шапки в 20px (смотри на картинке на самую верхнуюю полосу). Тогда как в iOS "шапка" накладывается поверх приложения и не занимает дополнительного места.

Кстати, особенность верстки в React Native - это возможность легко брать высоту и ширину экрана с помощью модуля Dimensions:

const height = Dimensions.get('window').height
const width = Dimensions.get('window').width


Ну а к верстке флексами привыкаешь быстро. Важно помнить, что если у блока не заданы ширина, высота или флекс > 0, то все внутренние элементы не будут показаны (!).

Не могу не упомянуть еще одну вещь, которую вы непременно будете использовать в своем приложении, - это генерация иконок приложения для Android и iOS. Их нужно иметь тысячу и одну, чтобы приложение красиво выглядело на любом устройстве. К счастью, имея всего node 6 и ImageMagick, а также исходное изображение не менее 200х200 пикселей, через командную строку можно получить все мыслимые и немыслимые иконки. В двух словах трех командах:

npm install -g yo generator-rn-toolbox
brew install imagemagick
yo rn-toolbox:assets --icon <path to your icon>


Дополнительные javascript библиотеки:

  • ramda - из полезного: работа с различными структурами данных, линзы.
  • moment - работа с датами.

Так как код выполняется с помощью javascript, то здесь может быть любой набор библиотек на усмотрение разработчика.

На этом можно было бы и закончить, добавив пару пафосных фраз, что "всё работает из коробки", "большое комьюнити", "огромное количество плагинов". Но реальность такова, что первое впечатление может быть обманчивым и нужно пройти долгий путь в iOS- и Андроид-разработке, прежде чем получить что-то, соответствующее настоящему приложению, которое бы решало какие-то пользовательские задачи.

  Подводные грабли:


Возможные ошибки в iOS:

- при создании билда в XCode сборка попадает в Other Items, из-за чего нельзя залить в AppStore.
Ошибка возникает из-за дополнительных библиотек, которые вы используете в проекте; при сборке они собираются не как используемые библиотеки, а самостоятельные проекты. Решение: во все проектах, которые находятся в Library нужно выставить
"Build Setting": Skip install = yes

- отсутствие обновления проекта при его изменении, "зависания" и прочие непредсказуемости
Одна из возможных причин кроется в том, что "clean project" в XCode не полностью удаляет создаваемые им временные файлы. Решение: удалить временные файлы вручную. Находятся они в директории:
cd /Users/[local machine]/Library/Developer/Xcode/DerivedData/

- при создании Архива для AppStore XCode ругается на дублирование файлов
Такое может произойти если вы используете pod и в нем реакт со своими компонентами, а так же часть из них напрямую из node_modules. Решение: исключить файлы при сборке проекта, добавив в ios/Podfile:

post_install do |installer|

  installer.pods_project.targets.each do |target|
    if target.name == "React"
      target.remove_from_project
    end
  end
end


Для Андроида желательно привести все используемые библиотеки к одной версии.

Заключение


Дорогу осилит идущий.

Разработка приложений на React Native - это удивительный процесс открытия новых вершин и радости от того, как по-другому могут строится вещи для других платформ. Это новый, еще только зарождающийся мир, в котором ты - первооткрыватель, пусть даже порой - первооткрыватель документации.

И осилив азы, можно приступать к проектированию своего первого приложения, задавая себе все новые и новые вопросы:

  • какие данные мы должны хранить в локальном сторе?
  • если приложение доступно онлайн, то как оно должно вести себя при отсутствии доступа к интернету?
  • в какой момент получать/отправлять данные?
  • что должен видеть пользователь в этот момент?
  • как и какие сообщения об ошибке показывать?
  • ...

    Комментарии

    andy128k написал(а)…
    Привет, Клёвая статья!

    Добавлю, что для тестирования компонентов очень удобно использовать Enzyme. Именно на react-native я сам не использовал, но вроде как можно.

    Странновато выглядит async функция с колбеками :)


    export const ensureExternalStorageIsAccessible = async () => {
    // only for Android 6 and greater
    if ((Platform.OS === 'android') && (Platform.Version > 22)) {
    const granted = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
    {
    title: 'App read external storage Permission',
    message: `App needs access to your external storage
    so you can take keep your data.`
    }
    )
    if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
    throw Error('Permission is not granted');
    }
    }
    }

    // а потом

    try {
    await ensureExternalStorageIsAccessible();
    // do job
    } catch (eeeh) {
    // sorry, maybe next time...
    }

    Популярные сообщения из этого блога

    Стайлгайд и компонентная разработка

    Прогноз погоды в консоли

    Вендорные префиксы