Инструменты
Еще раз хочу осветить тему рабочих инструментов. 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 разных библиотеки:
Да и вообще, любая задача может быть решена как угодно (ну, почти). И это самое интересное в реактиве.
Компоненты
Отдельного упоминания заслуживают компоненты. Для ребят с веба, это привычный инструмент, а вот для нас, ребят с мобилок — это просто серебряная пуля.
Тут у нас 3 разные кнопки. На самом деле не разные, это один компонент. Понимаете масштаб крутизны компонентов? Тут от слова «совсем» можно забыть про копипасту в верстке. Да, в андроиде есть стили, которые теоретически, должны избавить нас от копипасты. Но ведь они применяются к чистым компонентам. Да, я могу задать стиль button, но что бы сделать кнопку как на картинке выше, одним button в андроиде не обойдешься. Это целый отдельный layout, где будет и TextView и ImageView и у всего этого, а так же у layout будут свои параметры стиля. И все 3 кнопки будут отличаться еще и различным количеством этих компонентов, где-то нету картинок, где-то 2 текста и т.п… Другими словами, сделать все эти 3 кнопки на андроиде не сверстав их 3 раза никак не получится. Ну а как получается это делать на реакте? Тут есть 3 щепотки магии:
- Props
- Отображение только тех элементов, что существуют
- Наложение стилей
Подробнее обо всем.
В андроиде мы сначала создаем компонент в 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, будут иметь огромное преимущество перед другими.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Комментарии (16)
undestroyer
18.07.2017 06:33React Native еще не пробовал, потыкал Ionic (Angular). Тоже вполне удобно. По ощущениям — если писать одно и то же на Java и JS (Ionic), то результат получится один и тот же, а времени и сил нужно меньше. Когда эти кроссплатформенные фреймворки научатся хорошо работать с аппаратной частью — я буду рад :)
MauzerTheCat
19.07.2017 06:28Может стрельнуть, а может и нет, в любом случае на данной стадии React Native требует хорошего запаса бубнов…
Simipa
19.07.2017 06:36Из всего кросплатформенного я ставлю именно на реакт. Во-первых, родитель в лице фэйсбука уже достаточно весомый аргумент, а во-вторых, теперь они каждый месяц собираются с другими командами, что бы обсуждать дальнейшее развитие продукта. Вот уже буквально недавно дали возможность создавать проекты вообще без единой строчки нативного кода. Да и уже в таком сыром виде, инструмент уже очень много может.
nobodyhave
18.07.2017 13:41+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
24.07.2017 13:14Я реакт пока еще особо не пробовал — он умеет общаться с другими андроид приложениями не через интенты?
Конечно, интенты, дип линки… + Всегда есть возможность написать мост.
superyarik
19.07.2017 06:28+2Упомянутая камера умеет и бар коды читать, тоже стандартный запрос.
С навигацией да, всё странно. Сейчас стандартом считается https://reactnavigation.org/punksta
23.07.2017 18:41Самом неожиданным в 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 пишется куда короче в простых случаях, но когда у вас сложная логика при смене экранов, придется писать велосипеды и костыли.
St007
24.07.2017 09:56После прочтения статьи осталось ощущение что автор делает только первые шаги?
Сам кодю на Qt для мобилок, присматриваюсь к ReactNative, но вот что можно делать в Qt из коробки:
— Все сделано на тех самых волшебных компонентах, более того команда Qt постаралась и реализовала кастомные стили.
— К любому компоненту (QML) можно прицепить тени (с настройкой цвета, прозрачности, радиуса и пр.), можно компонент развернуть в 3D плоскости.
— К любому компоненту можно добавить шейдерный эффект, анимацию в два клика
— Довольно простая интеграция с нативным кодом (это если хочется использовать нативные Toast для Андроид, например)
— Развитая IDE
— Поддержка мультиязычности (в кода вместо строки «строка» пишем tr(«строка») и потом оно само создаст список фраз для перевода)
В общем, много удобств и полезностей и не забываем, что под капотом у Qt мотор на С++.
Сам пробовал ReactJs, концепция когда компонент хранит и отображает свое состояние показалась не очень удобной, так, если в обычном input редактировать текст, то каждый символ вызывает волну перезаписи свойств этих компонентов что в итоге сильно просаживает производительность.
NickWickedSick
24.07.2017 13:12Статья не очень соответствует своему названию.
Где тут раскрыт вопрос разработки с колокольни Android? Хотелось бы увидеть какой-то реальный опыт преодоления трудностей и несовершенств ReactNative. А так это просто обзорная статься А-ля «смотрите какой RN классный, но с косяками», коих уже и так полно.
sergeyfitis
24.07.2017 13:12Цвет тени
Как у тени может быть цвет? Это просто не логично. Тень — участок поверхности или область пространства, менее ярко освещённые по сравнению с прочими, скрытые от прямых лучей света.
Fractalzombie
В vs code для открытия нескольких файлов, можно использовать двойной клик.
comerc
Божечки, наконец-то!
indestructable
Есть настройка
"workbench.editor.enablePreview": false
, которая отключает режим просмотра.