React Native с колокольни Android разработки часть 2 +4

- такой же как Forbes, только лучше.

Свою прошлую статью я написал спустя несколько дней, после того, как я вообще начал ковыряться в react native, до этого имея опыт только в нативной разработке под android и iOS. Спустя это время я уже успел поработать над реальным react native проектом. И теперь хочу осветить все очевидные и неочевидные моменты с которыми я столкнулся в момент работы с реальным проектом. Всем заинтересованным под кат.

Инструменты


Еще раз хочу осветить тему рабочих инструментов. React native еще не очень близок к версии, хотя бы, 1.0, чему и причина отсутствия полностью рабочего и заточенного под этот продукт IDE. Хотя, внезапно, я наткнулся на это: Deco IDE. Да, это самая настоящая IDE (только под macOS по понятным причинам), да еще и купленная airbnb. Но не все так радужно как оказалось. Да, тут можно «программировать мышкой» просто перетаскивая компоненты в код. Опять же, есть список компонентов, не нужно каждый раз лезть на оф. сайт, чтобы узнать, а какой компонент еще там есть. Так же можно запустить проект буквально 1 тыком (правда, только iOS, с андроидом всегда проблемы). Но на этом все фишки и кончаются. Тут нету ни быстрых переходов к компонентам по клику с зажатым cmd, нету даже адекватного линтера и автодополнения. По функционалу кодинга — это простой блокнот, который только не закрытый тэг сможет подсветить. Но теперь этим инструментом занята крупная компания, надеюсь на его скорое развитие.

В большинстве видео про react native, а так же в скриншотах различных статей я везде видел VS code. Штука действительно неплохая, спокойно подцепляется eslinter как плагин, можно подцепить flow, есть автокомплиты и даже переходы к компонентам. Есть встроенный git и даже интегрированный терминал. И я бы тоже его использовал, но есть огромный для меня минус — по дефолту каждый открытый файл открывается в одной вкладке, как бы заменяя предыдущий. Чтобы открыть 2 вкладки с разными файлами, нужно начать редактирование в файле, затем открывать другой, который уже и откроется во второй вкладке. Если нужно просто быстро просмотреть 2-3 разных файла, обивку на стуле приходится менять это приносит некий дискомфорт.

Поэтому я все так же остановился на Nuclide, правда, подцепив flow, что сильно улучшает автокомплит, добавляет быстрые переходу к компонентам по клику, плюс все фишки с типизацией. Про красивые и удобные запуски проектов в 1 клик пока что приходится забыть.

Работа с камерой, картой и другими сложными вещами


Это, пожалуй, наиболее интересный вопрос для всех. Плохая новость — дефолтных компонентов для камеры и карты нету. Нужно использовать нативный код. Хорошая новость — все уже давно сделано до нас:

  • Дико крутые карты под авторством airbnb. Использовал лично, все замечательно работает как на iOS, так и на андроид, так же отлично кастомизируется.
  • Камера уже тоже есть. Хотя, лично не пробовал, небыло необходимости, хотя и любопытно.
  • В геопозицию, благо, умеет из коробки.

Вообще, уже есть куча рабочих компонентов, нужно просто погуглить. Но можно написать и самому.

Рабочий процесс


У react native есть только 1 проблема — андроид проблемы с андроидом. Уж не знаю, проблемы ли это системы или разработчиков, что клали болт на андроид, но с ним вечно какие-то странные косяки.
Самый странный случай: Date переведенный в строку формата: «YYYY-MM-DD HH:mm:ss» имеет разную длину символов на iOS и android, догадайтесь на какой платформе лишний пробел? Что приводит просто к лютой парное, вот казалось бы, код на чистом js, все работает замечательно на iOS, а на андроиде что-то может пойти не так. Поэтому ВСЕГДА нужно проверят приложение на обеих платформах после ЛЮБОГО изменения кода, никогда не знаешь в какую проблему это может вылиться.

На самом деле подобная проблема была единична для меня, почему-то криво работает Date на андроиде, а вот momentJS прекрасно. Так что сразу используйте последнее. А вот с версткой проблемы другого характера.
Во-первых, андроид вообще не умеет в тени, что указываются в стилях. Для него есть отдельный параметр — 'elevation', но только и всего. Цвет тени, радиус, прозрачность — все это проходит мимо андроида.
Во-вторых, разрешение экранов. У яблофонов просто огромные разрешения, особенно в плюсах, от чего, бывают проблемы, когда выставляешь кнопки с нужными размерами шрифтов, на iOS все смотрится хорошо, на андроиде все слипается — экран маловат будет. Благо, react native дает возможность определить платформу, на которой запустилось приложение, и от этого изменять что-то в коде, например, стили.

Что касается самого процесса разработки, то тут сложно описать то чувство свободы, которое ты обретаешь, после нативной разработки под android. Android SDK дает нам инструменты, предназначенные для чего-то конкретного, отойти от которых никак нельзя. Вот было придумано, что должна быть активити, в которой подцепляется класс к layout, и хоть что ты делай, а активити быть должна, даже сам гугл с этим ничего поделать не может. Вот дали они нам data binding, и вот используя эту библиотеку активити в 99% случаев используется как костыль, просто чтобы подцепить layout и ViewModel, попутно передав Model, хотя мы в layout'е уже явно указали и model и ViewModel. Абсолютно никакой логики в этом случае тут нету, а активити есть. Для передачи информации нужен Intent, а он без проблем может передавать только простые типы, а если хочется передать объект, то все, здравствуй Parcelable.
И таких примеров очень много. В случае с react native есть только… JavaScript и все. Ты сам решаешь как сделать тот или иной элемент. Именно поэтому для навигации можно использовать аж 3 разных библиотеки:


Да и вообще, любая задача может быть решена как угодно (ну, почти). И это самое интересное в реактиве.

Компоненты


Отдельного упоминания заслуживают компоненты. Для ребят с веба, это привычный инструмент, а вот для нас, ребят с мобилок — это просто серебряная пуля.
image
Тут у нас 3 разные кнопки. На самом деле не разные, это один компонент. Понимаете масштаб крутизны компонентов? Тут от слова «совсем» можно забыть про копипасту в верстке. Да, в андроиде есть стили, которые теоретически, должны избавить нас от копипасты. Но ведь они применяются к чистым компонентам. Да, я могу задать стиль button, но что бы сделать кнопку как на картинке выше, одним button в андроиде не обойдешься. Это целый отдельный layout, где будет и TextView и ImageView и у всего этого, а так же у layout будут свои параметры стиля. И все 3 кнопки будут отличаться еще и различным количеством этих компонентов, где-то нету картинок, где-то 2 текста и т.п… Другими словами, сделать все эти 3 кнопки на андроиде не сверстав их 3 раза никак не получится. Ну а как получается это делать на реакте? Тут есть 3 щепотки магии:

  1. Props
  2. Отображение только тех элементов, что существуют
  3. Наложение стилей

Подробнее обо всем.
В андроиде мы сначала создаем компонент в layout'е, затем находим его по ID'шнику в активити и передаем какие-то параметры, например, текст меняем. Это работает, если мы заранее знаем что хотим отобразить. В реактиве мы же указываем какой нам создать компонент с НУЖНЫМИ нами параметрами. В чем соль? В props мы можем передавать ВСЕ ЧТО УГОДНО, без каких либо проблем, начиная от простых типов, заканчивая объектами. Допустим, нам нужна еще 1 кнопка, такая же как по середине, только с другой стрелочкой. В андроиде мы бежим рисовать уже 4-ю кнопку, а тут же мы просто передаем через props другую иконку.

Но бОльшая магия твориться вот тут:

{true && <Text>Я существую</Text>}
{false && <Text>Я НЕ существую</Text>} 

Смысл в том, что так можно не отображать несуществующие объекты. Мы ведь используем JS с динамической типизацией, и ей можно удобно пользоваться для себя, например:

const text = this.props.text;
{text && <Text> {text} </Text> 

Если мы передали в props параметр text, то компонент его отрисует, а если не передали, то не отрисует, ибо зачем? Стоит еще раз акцентировать внимание на динамическую типизацию. С текстом все хорошо, текст есть — true, текста нету — false, тоже и с объектами. А вот с числами беда, отправите 0 — JS будет думать что это false… Для чисел лучше более явно проверять тип.
Начинает доходить логика? Мы делаем компонент, который учитывает все возможные варианты того, что в нем может находится, оборачивая их в конструкцию, что я представил выше.
И тут может возникнуть другая проблема — слишком большой текст, слишком большая картинка и прочее могут сломать внешний вид компонента. Тут нам на помощь приходит пункт номер 3:


<Text
style={[styles.defaultStyle, this.props.customStyle]}>
{this.props.text}
</Text>

Стиль мы определяем как массив стилей. Что это значит? Это значит, что если мы НЕ передали в props свой стиль, то компонент будет в дефолтном, который мы определили заранее. Но что, если мы передадим в кастомный стиль 1 параметр, допустим, отступ сверху? И этот компонент будет иметь дефолтный стиль плюс отступ сверху. Смысл в том, что всегда ПОЛНОСТЬЮ применяется дефолтный стиль, только в нем заменяются лишь те параметры, которые мы передаем в кастомном стиле. Т.е. если мы хотим только изменить цвет текста — не беда, размеры, отступы и прочие радости не слетят. А если нам какой-то параметр в стиле не нужен, мы передаем в кастомном стиле этот параметр со значением null.

Заключение


Еще можно упомянуть про работу с данными через redux, но это отдельная философия, рассчитанная на полноразмерные статьи. Скажу за себя, после нативной разработки я прошел все 5 стадий принятия неизбежного, когда работал с redux. Но потом я втянулся и очень зауважал такой подход.

Самый главный вопрос для кого react native? Да для всех. Делая продукт, нужно держать 2 команды разрабов — для iOS и android. Тут же хватит и одной. Во-первых, это тупо дешевле, нужно в 2 раза меньше людей, а во-вторых, удобно — появился баг, поправил сразу на 2 платформы. И серьезные ребята тоже начали втягиваться. Тут уже не только фейсбук и инстаграмм. Airbnb, walmart, testa, думаю, эти ребята что-то знают)

Да и потом, проект еще даже не близок к релизу версии 1.0, а им уже заинтересованны многие именитые ребята, которые собираются вместе для развития проекта. У нас есть уникальный шанс сесть не на уезжающий поезд, а на проезд, который еще даже не доехал до станции. Все кто овладел этим инструментом (особенно те, у кого есть опыт нативной разработки под мобилки) еще до массового релиза версии 1.0, будут иметь огромное преимущество перед другими.
А вы пробовали писать на react native?

Проголосовало 130 человек. Воздержалось 32 человека.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.



Комментарии (16):

  1. Fractalzombie
    /#10315950 / +4

    В vs code для открытия нескольких файлов, можно использовать двойной клик.

    • indestructable
      /#10316348 / +2

      Есть настройка "workbench.editor.enablePreview": false, которая отключает режим просмотра.

  2. svoka
    /#10316202

    Примеры выглядят немного притянутыми.
    Например, что мешает в андроиде сделать свой view с нужными стилями?

    • dzigoro
      /#10317002 / +1

      Ага.

      в Android:

      1. Напиши разметку
      2. Напиши back-класс
      3. Напиши 4 конструктора
      4. Напиши чтение AttributeSet

      в RN:

      1. Напиши разметку
      2. Готово

  3. undestroyer
    /#10316502

    React Native еще не пробовал, потыкал Ionic (Angular). Тоже вполне удобно. По ощущениям — если писать одно и то же на Java и JS (Ionic), то результат получится один и тот же, а времени и сил нужно меньше. Когда эти кроссплатформенные фреймворки научатся хорошо работать с аппаратной частью — я буду рад :)

    • MauzerTheCat
      /#10318354

      Может стрельнуть, а может и нет, в любом случае на данной стадии React Native требует хорошего запаса бубнов…

      • Simipa
        /#10318358

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

  4. nobodyhave
    /#10317034 / +1

    Во-вторых, разрешение экранов. У яблофонов просто огромные разрешения, особенно в плюсах, от чего, бывают проблемы, когда выставляешь кнопки с нужными размерами шрифтов, на iOS все смотрится хорошо, на андроиде все слипается — экран маловат будет.

    iPhone 7+: 5.5" 1920-by-1080-pixel resolution at 401 ppi
    LG G6: экран 5.7", разрешение 2880x1440 при 565 ppi

    Вот было придумано, что должна быть активити

    И придумана не просто так. Активити отвечает за жизненный цикл.

    Для передачи информации нужен Intent, а он без проблем может передавать только простые типы, а если хочется передать объект, то все, здравствуй Parcelable.

    Потому, что он в том числе используется для IPC. Я реакт пока еще особо не пробовал — он умеет общаться с другими андроид приложениями не через интенты?

    Тут у нас 3 разные кнопки.

    Тут у нас всего одна кнопка, для которой можно сделать
    setCompoundDrawables(@Nullable Drawable left, @Nullable Drawable top, @Nullable Drawable right, @Nullable Drawable bottom)

    А вообще хотелось бы больше примеров реакта, как в первой части статьи :)

    • ovi07
      /#10325298

      Я реакт пока еще особо не пробовал — он умеет общаться с другими андроид приложениями не через интенты?

      Конечно, интенты, дип линки… + Всегда есть возможность написать мост.

  5. superyarik
    /#10318352 / +2

    Упомянутая камера умеет и бар коды читать, тоже стандартный запрос.

    С навигацией да, всё странно. Сейчас стандартом считается https://reactnavigation.org/

    • punksta
      /#10324598

      Самом неожиданным в https://reactnavigation.org/ оказалось отсутствие способа понять внутри экрана, что он ушел на задний план в общем случае. Условно: не реализовано аналогов onResume, onPause.
      https://github.com/react-community/react-navigation/issues/51 вот тут пол года обсуждают как это должно быть написано: hoc, подписка на ивенты или функции компонента.

      Есть экспериментальная либа https://github.com/satya164/react-navigation-addons. Сейчас написал костыль над ней, чтобы все работало как привычно.

      Еще разные navigator-ы по разному управляют компонентами экрана, и у вас не всегда есть контроль над этим. Если у вас на ios табы, на на android drawer, то логика монтирования экранов будет разной: табы грузятся сразу, drawer грузит только текущий экран. В сочетании с первым недостатком писать немного больно.

      навигация на react-native пишется куда короче в простых случаях, но когда у вас сложная логика при смене экранов, придется писать велосипеды и костыли.

  6. gadfi
    /#10324696

    а чем вам webstorm не угодил?

  7. St007
    /#10324962

    После прочтения статьи осталось ощущение что автор делает только первые шаги?
    Сам кодю на Qt для мобилок, присматриваюсь к ReactNative, но вот что можно делать в Qt из коробки:
    — Все сделано на тех самых волшебных компонентах, более того команда Qt постаралась и реализовала кастомные стили.
    — К любому компоненту (QML) можно прицепить тени (с настройкой цвета, прозрачности, радиуса и пр.), можно компонент развернуть в 3D плоскости.
    — К любому компоненту можно добавить шейдерный эффект, анимацию в два клика
    — Довольно простая интеграция с нативным кодом (это если хочется использовать нативные Toast для Андроид, например)
    — Развитая IDE
    — Поддержка мультиязычности (в кода вместо строки «строка» пишем tr(«строка») и потом оно само создаст список фраз для перевода)
    В общем, много удобств и полезностей и не забываем, что под капотом у Qt мотор на С++.

    Сам пробовал ReactJs, концепция когда компонент хранит и отображает свое состояние показалась не очень удобной, так, если в обычном input редактировать текст, то каждый символ вызывает волну перезаписи свойств этих компонентов что в итоге сильно просаживает производительность.

  8. NickWickedSick
    /#10325292

    Статья не очень соответствует своему названию.
    Где тут раскрыт вопрос разработки с колокольни Android? Хотелось бы увидеть какой-то реальный опыт преодоления трудностей и несовершенств ReactNative. А так это просто обзорная статься А-ля «смотрите какой RN классный, но с косяками», коих уже и так полно.

  9. sergeyfitis
    /#10325294

    Цвет тени

    Как у тени может быть цвет? Это просто не логично. Тень — участок поверхности или область пространства, менее ярко освещённые по сравнению с прочими, скрытые от прямых лучей света.