Table of Contents
URL: https://www.progressiverobot.com/react-react-native-navigation-ru/
Введение
React Navigation — это популярная библиотека для организации маршрутизации и навигации в приложении React Native.
Эта библиотека помогает решить проблему навигации между различными экранами и использования общих данных различными экранами.
После изучения данного руководства у вас в распоряжении будет самая элементарная социальная сеть. Она будет отображать количество связей, которое есть у пользователя, и обеспечит метод установления связи с новыми друзьями. Вы сможете использовать это образец приложения для изучения возможностей навигации между экранами мобильного приложения, реализуемых с помощью react-navigation.
Предварительные требования
Для завершения данного обучающего модуля вам потребуется:
- Локальная среда разработки для Node.js. Выполните действия, описанные в статье Установка Node.js и создание локальной среды разработки.
- Вам может пригодиться знакомство с настройкой среды для создания нового проекта React Native и использованием эмуляторов iOS или Android.
Примечание: если у вас есть опыт работы с react-navigation в прошлом, вы можете заметить ряд различий. Вы можете ознакомиться с документацией, где вы найдете информацию по миграции с версии 3.x и миграции с версии 4.x.
Работоспособность инструкция данного руководства была проверена на Node v14.7.0, npm v6.14.7, react v16.13.1, react-native v0.63.2, @react-navigation/native v5.7.3 и @react-navigation/stack v5.9.0.
Шаг 1 — Создание нового приложения React Native
В первую очередь необходимо создать новое приложение React Native с помощью следующей команды в терминале:
npx react-native init <^>MySocialNetwork<^> --version <^>0.63.2<^>
Затем перейдите в новый каталог:
cd <^>MySocialNetwork<^>
Запустите приложение для iOS:
npm run ios
Или воспользуйтесь Android:
npm run android
Примечание: в случае возникновения проблем вы можете ознакомиться со статьей, посвященной устранению проблем с React Native CLI.
В результате будет создана заготовка проекта. В настоящее время он не очень походит на социальную сеть. Давайте исправим это.
Откройте файл App.js:
nano App.js
Замените содержимое App.js на следующий код, отображающий приветственное сообщение:
[label App.js]
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Welcome to MySocialNetwork!</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default App;
Сохраните файл. Теперь, когда вы запустите приложение, сообщение Welcome to MySocialNetwork! будет отображаться в вашем эмуляторе.
В следующем шаге мы добавим в наше приложение новые экраны.
Шаг 2 — Создание HomeScreen и FriendsScreen
В настоящее время у вас есть один экран, отображающий приветственное сообщение. В этом шаге мы создадим два новых экрана для вашего приложения: HomeScreen и FriendsScreen.
HomeScreen
Вашему приложению потребуется домашний экран HomeScreen. Экран HomeScreen будет отображать количество друзей, уже находящихся в вашей сети.
Возьмите код из файла App.js и добавьте его в новый файл с именем HomeScreen.js:
cp App.js HomeScreen.js
Откройте файл HomeScreen.js:
nano HomeScreen.js
Измените содержание файла HomeScreen.js для использования экрана HomeScreen вместо экрана App:
[label HomeScreen.js]
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class <^>HomeScreen<^> extends React.Component {
render() {
return (
<View style={styles.container}>
<Text><^>You have (undefined) friends.<^></Text>
</View>
);
}
}
// ...
export default <^>HomeScreen<^>;
Данный код будет генерировать сообщение-заглушку You have (undefined) friends. Точное значение вы получите позже.
FriendsScreen
Вашему приложению также потребуется дополнительный экран FriendsScreen. На экране FriendsScreen вы сможете добавлять новых друзей.
Возьмите код из файла App.js и добавьте его в новый файл с именем FriendsScreen.js:
cp App.js FriendsScreen.js
Откройте файл FriendsScreen.js:
nano FriendsScreen.js
Измените содержание файла FriendsScreen.js для использования экрана FriendsScreen вместо экрана App:
[label FriendsScreen.js]
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
class <^>FriendsScreen<^> extends React.Component {
render() {
return (
<View style={styles.container}>
<Text><^>Add friends here!<^></Text>
</View>
);
}
}
// ...
export default <^>FriendsScreen<^>;
Данный код будет добавлять текст Add friends here! в сообщение.
На данный момент у вас есть экраны HomeScreen и FriendsScreen. Однако вы не можете перемещаться между этими экранами. Вы реализуете данный функционал в следующем шаге.
Шаг 3 — Использование StackNavigator в React Navigation
Для навигации между экранами вы будете использовать StackNavigator. StackNavigator работает точно так же, как стек вызовов). Каждый экран, на который вы переходите, помещается на самый верх стека. Каждый раз, когда вы нажимаете кнопку назад, экраны удаляются с верхней части стека.
Сначала установите @react-navigation/native:
npm install @react-navigation/native<^>@5.7.3<^>
Затем установите @react-navigation/stack и соответствующие зависимости:
npm install @react-navigation/stack<^>@5.9.0<^> @react-native-community/masked-view<^>@0.1.10<^> react-native-screens<^>@2.10.1<^> react-native-safe-area-context<^>@3.1.4<^> react-native-gesture-handler<^>@1.7.0<^>
Примечание: если вы выполняете разработку под iOS, вам, возможно, потребуется перейти в каталог ios и запустить команду pod install.
Затем снова откройте файл App.js:
nano App.js
Добавьте в поддержку NavigationContainer и createStackNavigator в файл App.js:
[label App.js]
<^>import 'react-native-gesture-handler';<^>
import React from 'react';
import { StyleSheet } from 'react-native';
<^>import { NavigationContainer } from '@react-navigation/native';<^>
<^>import { createStackNavigator } from '@react-navigation/stack';<^>
<^>const Stack = createStackNavigator();<^>
Затем замените содержимое функции render:
[label App.js]
// ...
class App extends React.Component {
render() {
return (
<^><NavigationContainer><^>
<^><Stack.Navigator><^>
<^></Stack.Navigator><^>
<^></NavigationContainer><^>
);
}
}
// ...
Внутри <Stack.Navigator> добавьте компонент HomeScreen:
[label App.js]
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
<^>import HomeScreen from './HomeScreen';<^>
const Stack = createStackNavigator();
class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<^><Stack.Screen<^>
<^>name="Home"<^>
<^>component={HomeScreen}<^>
<^>/><^>
</Stack.Navigator>
</NavigationContainer>
);
}
}
// ...
Данный код создает очень компактный стек для вашего навигатора с одним экраном: HomeScreen.
Внутри <Stack.Navigator> добавьте компонент FriendsScreen:
[label App.js]
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './HomeScreen';
<^>import FriendsScreen from './FriendsScreen';<^>
const Stack = createStackNavigator();
class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<^><Stack.Screen<^>
<^>name="Friends"<^>
<^>component={FriendsScreen}<^>
<^>/><^>
</Stack.Navigator>
</NavigationContainer>
);
}
}
// ...
Этот код добавляет в навигатор экран FriendsScreen.
Примечание: данный способ отличается от того, как createStackNavigator использовался в предыдущих версиях React Navigation.
Теперь навигатор знает о двух ваших экранах.
Добавление кнопок на экраны HomeScreen и FriendsScreen
В конце добавьте кнопки для перехода между двумя экранами.
В файле HomeScreen.js добавьте следующий код:
[label HomeScreen.js]
import React from 'react';
import { StyleSheet, Text, View<^>, Button<^> } from 'react-native';
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have (undefined) friends.</Text>
<^><Button<^>
<^>title="Add some friends"<^>
<^>onPress={() =><^>
<^>this.props.navigation.navigate('Friends')<^>
<^>}<^>
<^>/><^>
</View>
);
}
}
// ...
В файле FriendsScreen.js добавьте следующий код:
[label FriendsScreen.js]
import React from 'react';
import { StyleSheet, Text, View<^>, Button<^> } from 'react-native';
class FriendsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
<^><Button<^>
<^>title="Back to home"<^>
<^>onPress={() =><^>
<^>this.props.navigation.navigate('Home')<^>
<^>}<^>
<^>/><^>
</View>
);
}
}
// ...
Давайте обсудим элемент this.props.navigation. Пока ваш экран включен в StackNavigator, он автоматически наследует множество полезных свойств объекта navigation. В этом случае вы использовали функцию navigate для перемещения на другую страницу.
Если вы сейчас откроете эмулятор, то сможете переходить между экранами HomeScreen и FriendsScreen.
Шаг 4 — Использование Context для передачи данных между экранами
В этом шаге мы создадим массив возможных друзей — Alice, Bob и Sammy — и пустой массив текущих друзей. Также нам потребуется создать функционал, позволяющий пользователю добавлять возможных друзей к своим текущим друзьям.
Откройте App.js:
nano App.js
Добавьте в состояние компонента элементы possibleFriends и currentFriends:
[label App.js]
// ...
class App extends React.Component {
<^>constructor(props) {<^>
<^>super(props)<^>
<^>this.state = {<^>
<^>possibleFriends: [<^>
<^>'Alice',<^>
<^>'Bob',<^>
<^>'Sammy',<^>
<^>],<^>
<^>currentFriends: [],<^>
<^>}<^>
<^>}<^>
// ...
}
// ...
Далее добавьте функцию для перемещения возможного друга в список текущих друзей:
[label App.js]
// ...
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
possibleFriends: [
'Alice',
'Bob',
'Sammy',
],
currentFriends: [],
}
}
<^>addFriend = (index) => {<^>
<^>const {<^>
<^>currentFriends,<^>
<^>possibleFriends,<^>
<^>} = this.state<^>
// Pull friend out of possibleFriends
<^>const addedFriend = possibleFriends.splice(index, 1)<^>
// And put friend in currentFriends
<^>currentFriends.push(addedFriend)<^>
// Finally, update the app state
<^>this.setState({<^>
<^>currentFriends,<^>
<^>possibleFriends,<^>
<^>})<^>
<^>}<^>
// ...
}
// ...
На этом мы завершили разработку функционала для добавления друзей.
Добавление контекста FriendsContext в приложение
Теперь вы можете добавлять друзей в файле App.js, но вам может потребоваться добавлять их в файле FriendsScreen.js и отображать количество друзей в файле HomeScreen.js. Поскольку данный проект разрабатывается с помощью React, вы можете внедрить данный функционал на ваши экраны с помощью контекста.
Примечание: в предыдущих версиях React Navigation существовала возможность использования screenProps для обмена данными между экранами. В текущей версии React Navigation рекомендуется использовать React Context для совместного использования данных различными экранами.
Чтобы избежать циклической зависимости, вам нужно создать новый файл FriendsContext:
nano FriendsContext.js
Экспортируйте FriendsContext:
[label FriendsContext]
import React from 'react';
export const FriendsContext = React.createContext();
Откройте App.js:
nano App.js
Импортируйте FriendsContext в файл:
[label App.js]
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
<^>import { FriendsContext } from './FriendsContext';<^>
import Home from './Home';
import Friends from './Friends';
const Stack = createStackNavigator();
class App extends React.Component {
// ...
render() {
return (
<^><FriendsContext.Provider><^>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
/>
<Stack.Screen
name="Friends"
component={Friends}
/>
</Stack.Navigator>
</NavigationContainer>
<^></FriendsContext.Provider><^>
);
}
}
// ...
Данный код определяет FriendsContext в качестве нового объекта типа Context и оборачивает NavigationContainer в компонент Context.Provider, чтобы любые дочерние элементы в дереве компонента могли подписаться на изменения контекста.
Так как вы больше не используете View или Text, вы можете удалить эти импорты из react-native.
Вы должны будете предоставить элемент value, чтобы сделать данные доступными потребителям:
[label App.js]
// ...
class App extends React.Component {
// ...
render() {
return (
<FriendsContext.Provider
<^>value={<^>
<^>{<^>
<^>currentFriends: this.state.currentFriends,<^>
<^>possibleFriends: this.state.possibleFriends,<^>
<^>addFriend: this.addFriend<^>
}<^><^>
<^>}<^>
>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
/>
<Stack.Screen
name="Friends"
component={Friends}
/>
</Stack.Navigator>
</NavigationContainer>
</FriendsContext.Provider>
);
}
}
// ...
Это позволит HomeScreen и FriendsScreen ссылаться на любые изменения в контексте для currentFriends и possibleFriends.
Теперь вы можете поработать над ссылками на контекст в ваших экранах.
Добавление контекста FriendsContext на экран HomeScreen
В этом шаге вы настроите отображения текущего количества друзей в приложении.
Откройте файл HomeScreen.js:
nano HomeScreen.js
Импортируйте FriendsContext в файл:
[label HomeScreen.js]
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
<^>import { FriendsContext } from './FriendsContext';<^>
class HomeScreen extends React.Component {
// ...
}
<^>HomeScreen.contextType = FriendsContext;<^>
// ...
Данный код определяет Class.contextType. Теперь вы можете получить доступ к контексту на ваших экранах.
Например, давайте заставим ваш экран HomeScreen отображать значение текущих друзей currentFriends для вас:
[label HomeScreen.js]
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { FriendsContext } from './FriendsContext';
class Home extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have <^>{ this.context.currentFriends.length }<^> friends!</Text>
<Button
title="Add some friends"
onPress={() =>
this.props.navigation.navigate('Friends')
}
/>
</View>
);
}
}
HomeScreen.contextType = FriendsContext;
// ...
Если снова открыть приложение в эмуляторе и перейти на экран HomeScreen, вы увидите сообщение: You have 0 friends!.
Добавление контекста FriendsContext на экран FriendsScreen
В этом шаге мы настроим отображение возможных друзей в приложении и предоставив кнопки для добавления возможных друзей в список текущих друзей.
Затем откройте файл FriendsScreen.js:
nano FriendsScreen.js
Импортируйте FriendsContext в файл:
[label FriendsScreen.js]
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
<^>import { FriendsContext } from './FriendsContext';<^>
class FriendsScreen extends React.Component {
// ...
}
<^>FriendsScreen.contextType = FriendsContext;<^>
// ...
Данный код определяет Class.contextType.
Теперь создайте кнопку для добавления друзей в файле FriendsScreen.js:
[label FriendsScreen.js]
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { FriendsContext } from './FriendsContext';
class Friends extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
<^>{<^>
<^>this.context.possibleFriends.map((friend, index) => (<^>
<^><Button<^>
<^>key={ friend }<^>
<^>title={ `Add ${ friend }` }<^>
<^>onPress={() =><^>
<^>this.context.addFriend(index)<^>
<^>}<^>
<^>/><^>
<^>))<^>
<^>}<^>
<Button
title="Back to home"
onPress={() =>
this.props.navigation.navigate('Home')
}
/>
</View>
);
}
}
FriendsScreen.contextType = FriendsContext;
// ...
Если вы снова запустите приложение в эмуляторе и перейдете на экран FriendsScreen, то увидите список друзей, которых можно добавить к текущим друзьям.
Если вы перейдете на экран FriendsScreen и нажмете кнопку для добавления друзей, то увидите, что список возможных друзей possibleFriends сократился. Если же перейти на экран HomeScreen, то можно увидеть, как выросло количество текущих друзей.
Теперь вы можете переходить между экранами и организовать обмен данными между ними.
Заключение
В этом руководстве вы создали образец приложения React Native с несколькими экранами. Используя React Navigation, вы реализовали способ навигации между экранами. Используя React Context, вы разработали способ обмена данными между экранами.
Если вы хотите глубже погрузиться в изучение React Navigation, ознакомьтесь с документацией.
React Navigation — это не единственное решение для маршрутизации и навигации. Существует также React Native Navigation, React Native Router Flux и React Router Native.
Если вы хотите узнать больше о React, почитайте нашу серию «Программирование на React.js» или посмотрите страницу тем React, где вы найдете упражнения и программные проекты.