Если вы фронтенд разработчик, да еще и с опытом работы 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 специалистов.
Ссылка на репозиторий