Свою прошлую статью я написал спустя несколько дней, после того, как я вообще начал ковыряться в 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 клик пока что приходится забыть.
Это, пожалуй, наиболее интересный вопрос для всех. Плохая новость — дефолтных компонентов для камеры и карты нету. Нужно использовать нативный код. Хорошая новость — все уже давно сделано до нас:
Вообще, уже есть куча рабочих компонентов, нужно просто погуглить. Но можно написать и самому.
У 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 щепотки магии:
Подробнее обо всем.
В андроиде мы сначала создаем компонент в layout'е, затем находим его по ID'шнику в активити и передаем какие-то параметры, например, текст меняем. Это работает, если мы заранее знаем что хотим отобразить. В реактиве мы же указываем какой нам создать компонент с НУЖНЫМИ нами параметрами. В чем соль? В props мы можем передавать ВСЕ ЧТО УГОДНО, без каких либо проблем, начиная от простых типов, заканчивая объектами. Допустим, нам нужна еще 1 кнопка, такая же как по середине, только с другой стрелочкой. В андроиде мы бежим рисовать уже 4-ю кнопку, а тут же мы просто передаем через props другую иконку.
Но бОльшая магия твориться вот тут:
Смысл в том, что так можно не отображать несуществующие объекты. Мы ведь используем JS с динамической типизацией, и ей можно удобно пользоваться для себя, например:
Если мы передали в props параметр text, то компонент его отрисует, а если не передали, то не отрисует, ибо зачем? Стоит еще раз акцентировать внимание на динамическую типизацию. С текстом все хорошо, текст есть — true, текста нету — false, тоже и с объектами. А вот с числами беда, отправите 0 — JS будет думать что это false… Для чисел лучше более явно проверять тип.
Начинает доходить логика? Мы делаем компонент, который учитывает все возможные варианты того, что в нем может находится, оборачивая их в конструкцию, что я представил выше.
И тут может возникнуть другая проблема — слишком большой текст, слишком большая картинка и прочее могут сломать внешний вид компонента. Тут нам на помощь приходит пункт номер 3:
Стиль мы определяем как массив стилей. Что это значит? Это значит, что если мы НЕ передали в props свой стиль, то компонент будет в дефолтном, который мы определили заранее. Но что, если мы передадим в кастомный стиль 1 параметр, допустим, отступ сверху? И этот компонент будет иметь дефолтный стиль плюс отступ сверху. Смысл в том, что всегда ПОЛНОСТЬЮ применяется дефолтный стиль, только в нем заменяются лишь те параметры, которые мы передаем в кастомном стиле. Т.е. если мы хотим только изменить цвет текста — не беда, размеры, отступы и прочие радости не слетят. А если нам какой-то параметр в стиле не нужен, мы передаем в кастомном стиле этот параметр со значением null.
Еще можно упомянуть про работу с данными через redux, но это отдельная философия, рассчитанная на полноразмерные статьи. Скажу за себя, после нативной разработки я прошел все 5 стадий принятия неизбежного, когда работал с redux. Но потом я втянулся и очень зауважал такой подход.
Самый главный вопрос для кого react native? Да для всех. Делая продукт, нужно держать 2 команды разрабов — для iOS и android. Тут же хватит и одной. Во-первых, это тупо дешевле, нужно в 2 раза меньше людей, а во-вторых, удобно — появился баг, поправил сразу на 2 платформы. И серьезные ребята тоже начали втягиваться. Тут уже не только фейсбук и инстаграмм. Airbnb, walmart, testa, думаю, эти ребята что-то знают)
Да и потом, проект еще даже не близок к релизу версии 1.0, а им уже заинтересованны многие именитые ребята, которые собираются вместе для развития проекта. У нас есть уникальный шанс сесть не на уезжающий поезд, а на проезд, который еще даже не доехал до станции. Все кто овладел этим инструментом (особенно те, у кого есть опыт нативной разработки под мобилки) еще до массового релиза версии 1.0, будут иметь огромное преимущество перед другими.
Инструменты
Еще раз хочу осветить тему рабочих инструментов. 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, будут иметь огромное преимущество перед другими.
Only registered users can participate in poll. Log in, please.
А вы пробовали писать на react native?
25.57% Да, для себя45
20.45% Да, для реального проекта36
37.5% Нет, но интересно попробовать66
16.48% Нет и не собираюсь пробовать29
176 users voted. 38 users abstained.