Если вы фронтенд разработчик, да еще и с опытом работы react + redux, то вам определенно стоит обратить внимание на такой интересный инструмент как react-native. Он позволяет разрабатывать кроссплатформенные приложения под ios и android. React-native находится в стадии активного развития и выпускает обновления каждый месяц.
Год назад у меня появилось желание попробовать эту технологию и я начал писать приложение-словарь, которое позволяет сохранять категорию английских слов с их переводом. Версия react-native на тот момент была 0.37, теперь версия 0.52. Несколько недель назад я решил возобновить разработку и столкнулся со стандартной проблемой быстрорастущих проектов, а именно довольно частая и кардинальная смена функциональности. Мне пришлось переписать некоторые вещи для того чтобы приложение запустилось. Вначале мне это сильно не понрав��лось, однако дальше я понял что эти изменения увеличивают скорость и качество разработки приложения. Дальше я бы хотел вкратце рассмотреть основные моменты разработки на react-native, c которыми я столкнулся в процессе.
На данный момент вы можете создать приложение 2 способами: с помощью create-react-native-app и react-native init. Create-react-native-app — это npm пакет, который позволяет вам создать начальную структуру приложения и запустить его на смартфоне без установки окружения для каждой из платформ. Однако если вам понадобится добавить в приложение нативный код или подключить библиотеку, которая это делает, то вам все равно придется устанавливать окружение.
И вот у вас уже есть готовый проект, а что же делать дальше? Ведь у нас нет ни CSS, ни HTML. Зато у нас есть jsx синтаксис, а также синтаксис для стилизации, очень похожий на inline стили в html. Для верстки макета используется flexbox такой же, как и на веб. В react-native нет привычных для фронтенд разработчика HTML элементов, вместо этого есть react-native компоненты для верстки, описание которых можно найти на официальном сайте. Есть кроссплатформенные компоненты(View, Button, TextInput), а также платформозависимые (DatePickerIOS, ProgressBarAndroid и другие). Давайте рассмотрим разработку компонента на примере создания карточки для отображения категории слов.

Ниже представлена jsx разметка для данного компонента.
View компонент похож на div в вебе и является одним из основных при создании компонента. TouchableNativeFeedback это компонент который позволяет обрабатывать нажатие на вложенный в него элемент. ColoredFlatButton и Icon компоненты из библиотеки react-native-material-kit. Как видим из примера выше верстка в react-native ничем не отличается от верстки в react, за исключением того, что используются компоненты из react-native вместо HTML элементов.
Дальше мы рассмотрим стилизацию этого компонента.
Для того чтобы создать стили нужно импортировать класс StyleSheet из react-native и передать ему объект стилей. Для применения стиля к элементу нужно указать его в атрибуте style.
Я думаю что в стилях мы не будем разбираться, человеку знакомому с css и так вcе понятно. Единственное отличие, так это то что размеры указываются не в CSS единицах измерения, а в Density-independent Pixels. Это единицы измерения которые позволяют приложению выглядеть одинаково на различных экранах и разрешениях в IOS и Android.
После того как в приложении появляется больше чем одна страница стоит задуматься как сделать переход между ними. До недавних пор добавить навигацию в приложение было достаточно сложно.
Приведу пример как это делалось раньше.
Согласитесь, выглядит не очень? Теперь ситуация изменилась, появилось несколько пакетов, которые рекомендуются в документации(native-navigation, react-native-navigation, react-navigation). Я использовал react-navigation. Все оказалось просто, достаточно импортировать navigator и указать настройки.
Первым параметром передаются маршруты приложения, а также можно указать настройки для header каждой страницы. Вторым параметром передаются настройки для компонента Drawer — это меню которое открывается слева по нажатию на бургер иконку. Есть возможность интеграции с redux.
После того как в приложении появилась навигация и несколько экранов, стоит задумать о сохранении данных. Если приложение не использует соединение с интернетом, тогда нужно хранить данные на устройстве. Для этого у нас есть SQLite. Для работы с бд я использовал пакет react-native-sqlite-storage. Немного повозился с установкой, а проблема оказалось очевидной, после добавления в проект этой библиотеки нужно было переустановить приложение на устройстве. Я использовал метод при котором в проекте уже есть база данных, которая используется при установке приложения на устройство, как это сделать описано на странице модуля в github. Для установки соединения нужна всего лишь одна строка.
А также простой пример запроса к базе данных.
В заключение могу сказать что после использования react-native я остался доволен данной технологией. Удобная отладка в браузере, никакого отличия от отладки веб приложений. Если какого-то функционала нет, всегда можно найти библиотеку в сообществе react-native специалистов.
Ссылка на репозиторий
Год назад у меня появилось желание попробовать эту технологию и я начал писать приложение-словарь, которое позволяет сохранять категорию английских слов с их переводом. Версия react-native на тот момент была 0.37, теперь версия 0.52. Несколько недель назад я решил возобновить разработку и столкнулся со стандартной проблемой быстрорастущих проектов, а именно довольно частая и кардинальная смена функциональности. Мне пришлось переписать некоторые вещи для того чтобы приложение запустилось. Вначале мне это сильно не понрав��лось, однако дальше я понял что эти изменения увеличивают скорость и качество разработки приложения. Дальше я бы хотел вкратце рассмотреть основные моменты разработки на react-native, c которыми я столкнулся в процессе.
На данный момент вы можете создать приложение 2 способами: с помощью create-react-native-app и react-native init. Create-react-native-app — это npm пакет, который позволяет вам создать начальную структуру приложения и запустить его на смартфоне без установки окружения для каждой из платформ. Однако если вам понадобится добавить в приложение нативный код или подключить библиотеку, которая это делает, то вам все равно придется устанавливать окружение.
И вот у вас уже есть готовый проект, а что же делать дальше? Ведь у нас нет ни CSS, ни HTML. Зато у нас есть jsx синтаксис, а также синтаксис для стилизации, очень похожий на inline стили в html. Для верстки макета используется flexbox такой же, как и на веб. В react-native нет привычных для фронтенд разработчика HTML элементов, вместо этого есть react-native компоненты для верстки, описание которых можно найти на официальном сайте. Есть кроссплатформенные компоненты(View, Button, TextInput), а также платформозависимые (DatePickerIOS, ProgressBarAndroid и другие). Давайте рассмотрим разработку компонента на примере создания карточки для отображения категории слов.

Ниже представлена jsx разметка для данного компонента.
<View style={[styles.card, customStyle]} elevation={5}> <TouchableNativeFeedback onPress={() => onCardBodyClick(categoryId, categoryName)} background={TouchableNativeFeedback.Ripple('black')} > <View style={styles.cardBody}> <Text style={styles.bodyText}>{categoryName}</Text> </View> </TouchableNativeFeedback> <View style={styles.cardActions}> <ColoredFlatButton onPress={() => onRemove(categoryId)}> <Icon size={18} name="close" color="grey" /> </ColoredFlatButton> <ColoredFlatButton onPress={() => onEdit(categoryId)}> <Icon size={18} name="mode-edit" color="grey" /> </ColoredFlatButton> <ColoredFlatButton onPress={() => onStudy(categoryId)}> <Icon size={18} name="school" color="grey" /> </ColoredFlatButton> </View> </View>
View компонент похож на div в вебе и является одним из основных при создании компонента. TouchableNativeFeedback это компонент который позволяет обрабатывать нажатие на вложенный в него элемент. ColoredFlatButton и Icon компоненты из библиотеки react-native-material-kit. Как видим из примера выше верстка в react-native ничем не отличается от верстки в react, за исключением того, что используются компоненты из react-native вместо HTML элементов.
Дальше мы рассмотрим стилизацию этого компонента.
const styles = StyleSheet.create({ card: { marginTop: 10, width: 160, height: 140, justifyContent: 'flex-end', }, cardBody: { flex: 1, padding: 16, justifyContent: 'flex-end', }, bodyText: { fontSize: 18, color: 'white', }, cardActions: { padding: 8, flexDirection: 'row', backgroundColor: 'white', justifyContent: 'space-between', alignItems: 'flex-end', }, });
Для того чтобы создать стили нужно импортировать класс StyleSheet из react-native и передать ему объект стилей. Для применения стиля к элементу нужно указать его в атрибуте style.
<View style={styles.cardActions}>
Я думаю что в стилях мы не будем разбираться, человеку знакомому с css и так вcе понятно. Единственное отличие, так это то что размеры указываются не в CSS единицах измерения, а в Density-independent Pixels. Это единицы измерения которые позволяют приложению выглядеть одинаково на различных экранах и разрешениях в IOS и Android.
После того как в приложении появляется больше чем одна страница стоит задуматься как сделать переход между ними. До недавних пор добавить навигацию в приложение было достаточно сложно.
Приведу пример как это делалось раньше.
const _navigator = null; class EnglishApp extends Component { onNavBackPress = () => { _navigator.pop(); }; renderScene = (route, navigator) => { _navigator = navigator; switch (route.id) { case routeIDs.NEW_WORD: return <SingleWordScreen navigator={navigator} onNavIconClicked={this.onNavBackPress} />; case routeIDs.WORD_LIST: return <WordListScreen navigator={navigator} onNavIconClicked={this.onNavBackPress} />; } }; render() { return ( <Navigator initialRoute={routeIDs.CATEGORY} renderScene={this.renderScene} configureScene={(route, routeStack) => Navigator.SceneConfigs.FloatFromRight} /> ); } }
Согласитесь, выглядит не очень? Теперь ситуация изменилась, появилось несколько пакетов, которые рекомендуются в документации(native-navigation, react-native-navigation, react-navigation). Я использовал react-navigation. Все оказалось просто, достаточно импортировать navigator и указать настройки.
const RootNavigator = DrawerNavigator( { [RoutesID.CATEGORY]: { screen: CategoryScreen, navigationOptions: { drawerLabel: 'Категории', drawerIcon: ({ tintColor }) => ( <Icon name="local-library" color={tintColor} size={22} /> ), }, }, [RoutesID.NEW_WORD]: { screen: NewWordScreen, navigationOptions: { drawerLabel: () => null, }, }, }, { drawerWidth: 250, drawerPosition: 'left', contentOptions: { inactiveTintColor: 'darkgray', }, drawerOpenRoute: 'DrawerOpen', drawerCloseRoute: 'DrawerClose', drawerToggleRoute: 'DrawerToggle', }, );
Первым параметром передаются маршруты приложения, а также можно указать настройки для header каждой страницы. Вторым параметром передаются настройки для компонента Drawer — это меню которое открывается слева по нажатию на бургер иконку. Есть возможность интеграции с redux.
После того как в приложении появилась навигация и несколько экранов, стоит задумать о сохранении данных. Если приложение не использует соединение с интернетом, тогда нужно хранить данные на устройстве. Для этого у нас есть SQLite. Для работы с бд я использовал пакет react-native-sqlite-storage. Немного повозился с установкой, а проблема оказалось очевидной, после добавления в проект этой библиотеки нужно было переустановить приложение на устройстве. Я использовал метод при котором в проекте уже есть база данных, которая используется при установке приложения на устройство, как это сделать описано на странице модуля в github. Для установки соединения нужна всего лишь одна строка.
open() { return SQLite.openDatabase({ name: 'englishAppDB.db', createFromLocation: 1 }).then( (db) => { this.db = db; Promise.resolve(); }, error => Promise.reject(error), ); }
А также простой пример запроса к базе данных.
getAllCategories() { return this.db.executeSql('SELECT * FROM category', []).then( ([{ rows }]) => { let category = new List(); for (let i = 0; i < rows.length; i += 1) { category = category.push(new CategoryRecord({ id: rows.item(i).Id, name: rows.item(i).name, color: rows.item(i).color, })); } return category; }, error => Promise.reject(error), ); }
В заключение могу сказать что после использования react-native я остался доволен данной технологией. Удобная отладка в браузере, никакого отличия от отладки веб приложений. Если какого-то функционала нет, всегда можно найти библиотеку в сообществе react-native специалистов.
Ссылка на репозиторий
