Разбираемся, чем может быть полезен Mobile-разработчику React.js из веб-фронтенда.
Итак, React Native — это библиотека от Facebook для построения пользовательского интерфейса из компонентов, как стандартных, так и пользовательских. Интерес к этой библиотеке обусловлен сразу несколькими факторами: это кроссплатформенность, хорошая производительность и подход к построению UI, позволяющий легко разбивать интерфейс на независимые компоненты.
Немного предыстории
Все началось с появления библиотеки React.js в веб-разработке. Около 5 лет назад компания Facebook впервые начала использовать ее у себя в ленте новостей, затем к числу пользователей присоединился Instagram. В 2013 году исходный код библиотеки был открыт, и ее популярность стала стремительно расти. Сейчас React входит в топ-5 самых популярных библиотек на GitHub и широко используется за пределами Facebook (например, такими компаниями, как Airbnb, Netflix и Uber).
Можно выделить три основных особенности React, благодаря которым этот подход «выстрелил»:
Разбиение UI на независимые компоненты, которые можно повторно использовать. Вы можете легко определять свои компоненты как функции или, что чаще, классы, наследующиеся от React.Component и реализующие метод render(), который возвращает дерево из других компонентов. Компоненту сверху передаются данные в виде свойств (props), на основе которых он вычисляет дерево UI-элементов.
Важная архитектурная особенность React — это однонаправленный поток данных (англ. one-way data flow). Это означает, что компонент не может изменять переданные ему сверху props, а для обработки любых событий от интерфейса следует использовать функции-коллбэки, также передаваемые как props. Это полезное свойство позволяет избежать так называемого спагетти-кода. Таким образом, цепочка действий упрощенно выглядит так:
- происходит событие UI (нажатие на кнопку);
- компонент кнопки вызывает коллбэк onClick, переданный ему сверху;
- из коллбэка выполняется некая бизнес-логика, изменяется состояние приложения;
- происходит обновление UI посредством рендера корневого компонента с новым состоянием приложения, переданным в том или ином виде как props.
Использование Virtual DOM. Применительно к мобильной разработке, термин не совсем корректный, но суть та же, что и в вебе — вместе с деревом элементов интерфейса, отображаемых на экране, в памяти строится его легковесная копия. При обновлении вычисляется diff между реальным и новым виртуальным деревом, и это позволяет обновлять на экране только те элементы, которые действительно изменились. В общем, этот подход позволяет упростить обновления UI до повторного рендера корневого компонента без тормозов и глюков.
В Facebook поняли, что этот же подход можно использовать для интерфейса мобильных приложений, и в 2015 году появился React Native, основанный на тех же принципах и имеющий набор типовых UI-элементов для мобильных приложений. Несмотря на малый возраст технологии, ее уже вовсю используют в продакшене. Приложения Facebook и Instagram — это React Native. Еще примеры реальных приложений — Airbnb, Bloomberg, JD.com, Discord, и это только наиболее известные.
Чем хорош?
Помимо описанных выше свойств, можно выделить явные плюсы использования данной библиотеки.
Наверное, это прежде всего кроссплатформенность — одно и то же приложение на RN можно запустить и под Android. Возможность получить Android-версию приложения, не прилагая почти никаких усилий, выглядит крайне заманчиво. Впрочем, здесь все не так однозначно, но об этом ниже.
Возможно, услышав слово JavaScript, вы подумали, что RN — это очередной метод завернуть браузер в приложение, но это не так. Слово Native в названии как раз указывает на то, что используются нативные элементы платформы — никакого HTML5. Тут будет очень кстати вариант Hello World из официальной документации, иллюстрирующий это свойство:
import React, { Component } from 'react';
import { Image, ScrollView, Text } from 'react-native';
class AwkwardScrollingImageWithText extends Component {
render() {
return (
<ScrollView>
<Image source={{uri: 'https://i.chzbgr.com/full/7345954048/h7E2C65F9/'}} />
<Text>
On iOS, a React Native ScrollView uses a native UIScrollView.
On Android, it uses a native ScrollView.
On iOS, a React Native Image uses a native UIImageView.
On Android, it uses a native ImageView.
React Native wraps the fundamental native components, giving you
the performance of a native app, plus the clean design of React.
</Text>
</ScrollView>
);
}
}
Поэтому с производительностью здесь лучше, чем в решениях на основе WebView. Однако, нативные языки (Swift/Objective-C/Java) все равно будут быстрее, об этом ниже.
Еще один плюс — скорость разработки. Помимо лаконичного и выразительного синтаксиса (пример выше будет понятен любому разработчику), этому способствует так называемый Hot Reloading — пересборка и изменение UI без перезапуска приложения, с сохранением его состояния. Это возможно благодаря тому, что React в каком-то смысле представляет интерфейс как функцию от данных (состояния приложения). Не трогая состояние приложения, динамически заменяется код (JavaScript же!), отвечающий за UI, и интерфейс заново рендерится. На мой взгляд, это очень круто и удобно, особенно когда нужно в краткие сроки сделать реально работающий прототип приложения.
Ну и наконец, то, что тяжело или невозможно реализовать на RN, всегда можно реализовать нативным кодом.
А в чем минусы?
Безусловно, React Native — это не серебряная пуля ото всех бед, и у него есть заметные минусы.
Многие отмечают малое количество доступных из коробки стандартных UI-элементов, что является следствием молодости технологии. Поэтому при разработке чего-либо сложного вам наверняка придется писать нативный код. Отсюда мы плавно переходим к следующему минусу.
Неполная кроссплатформенность. Если вы пишете нативные расширения, то вам придется писать их для каждой платформы. А без этого зачастую не обойтись.
Как ни странно, но в качестве минуса можно упомянуть… производительность. Да, RN быстрее, чем WebView, но все же медленнее нативного кода. Все дело в том, что на iOS движок JavaScriptCore не использует и не может использовать JIT-компиляцию ввиду того факта, что на iOS обычное приложение не может иметь участки памяти с разрешением на выполнение и запись одновременно. Напомню, что JIT-компиляция — это преобразование байт-кода в машинный на лету, во время выполнения программы, т. е. генерация исполняемого кода на лету, что в iOS невозможно. В JavaScript-движках JIT хорошо развит и позволяет в разы ускорить код, поэтому отсутствие JIT означает невозможность писать «тяжелые» вычисления на JS, и это опять приводит к необходимости написания нативного кода в некоторых случаях.
React — это только представление (View). Выбор реализации бизнес-логики остается за программистом. Это означает, что React не является фреймворком, полностью охватывающим все детали разработки, чего многие от него ожидают. React — это именно библиотека, решающая конкретную задачу. Ввиду этого, нет единого подхода к разработке приложений на React, и части, отвечающие за логику и данные все делают по-своему. Наиболее популярным решением является библиотека Redux.
Заключение
Лично у меня сложилось положительное впечатление об этой технологии, так как ее подход выгодно отличается от решений вроде PhoneGap. Однако, несмотря на хайп вокруг этой библиотеки, нужно знать об ее недостатках и понимать, что в некоторых случаях этот вариант не подойдет. Будем надеяться, что React Native со временем избавится от своих «детских болячек» и сможет стать достойным конкурентом таким зрелым платформам, как Appcelerator, PhoneGap и Xamarin.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.