Использование маршрутизации React Navigation в React Native

Введение

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 на следующий код, отображающий приветственное сообщение:

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:

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:

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:

Затем установите @react-navigation/stack и соответствующие зависимости:

Примечание: если вы выполняете разработку под iOS, вам, возможно, потребуется перейти в каталог ios и запустить команду pod install.

Затем снова откройте файл App.js:

  • nano App.js

Добавьте в поддержку NavigationContainer и createStackNavigator в файл App.js:

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:

App.js

// ...  class App extends React.Component {   render() {     return (       <NavigationContainer>         <Stack.Navigator>         </Stack.Navigator>       </NavigationContainer>     );   } }  // ... 

Внутри <Stack.Navigator> добавьте компонент HomeScreen:

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:

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 добавьте следующий код:

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 добавьте следующий код:

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

Если вы сейчас откроете эмулятор, то сможете переходить между экранами HomeScreen и FriendsScreen.

Шаг 4 — Использование Context для передачи данных между экранами

В этом шаге мы создадим массив возможных друзей — Alice, Bob и Sammy — и пустой массив текущих друзей. Также нам потребуется создать функционал, позволяющий пользователю добавлять возможных друзей к своим текущим друзьям.

Откройте App.js:

  • nano App.js

Добавьте в состояние компонента элементы possibleFriends и currentFriends:

App.js

// ...  class App extends React.Component {   constructor(props) {     super(props)     this.state = {       possibleFriends: [         'Alice',         'Bob',         'Sammy',       ],       currentFriends: [],     }   }    // ... }  // ... 

Далее добавьте функцию для перемещения возможного друга в список текущих друзей:

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:

FriendsContext

import React from 'react';  export const FriendsContext = React.createContext(); 

Откройте App.js:

  • nano App.js

Импортируйте FriendsContext в файл:

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, чтобы сделать данные доступными потребителям:

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 в файл:

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 для вас:

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 в файл:

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:

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, то увидите список друзей, которых можно добавить к текущим друзьям.

Экран HomeScreen со значением 0 для списка текущих друзей currentFriends и экран FriendScreen со значением 3 для списка возможных друзей possibleFriends

Если вы перейдете на экран FriendsScreen и нажмете кнопку для добавления друзей, то увидите, что список возможных друзей possibleFriends сократился. Если же перейти на экран HomeScreen, то можно увидеть, как выросло количество текущих друзей.

Теперь вы можете переходить между экранами и организовать обмен данными между ними.

Заключение

В этом руководстве вы создали образец приложения React Native с несколькими экранами. Используя React Navigation, вы реализовали способ навигации между экранами. Используя React Context, вы разработали способ обмена данными между экранами.

Полный исходный код этого проекта доступен на GitHub.

Если вы хотите глубже погрузиться в изучение React Navigation, ознакомьтесь с документацией.

React Navigation — это не единственное решение для маршрутизации и навигации. Существует также React Native Navigation, React Native Router Flux и React Router Native.

Если вы хотите узнать больше о React, почитайте нашу серию «Программирование на React.js» или посмотрите страницу тем React, где вы найдете упражнения и программные проекты.