Перейти к содержимому

Практика 5. Практическая работа 5. Навигация и передача параметров

Цели работы

  • Освоить два основных навигатора React Navigation: Stack (стек экранов) и Tab (нижние вкладки).
  • Научиться переходить между экранами и передавать параметры (id, имя) через navigation.navigate.
  • Научиться читать параметры на целевом экране через route.params и возвращаться назад.
  • Собрать рабочий граф экранов: Tab на верхнем уровне, со Stack внутри вкладки.

Коротко о теории

  • Экран — обычный React-компонент. Навигатор — компонент, который хранит группу экранов и управляет переходами между ними.
  • Всё дерево навигаторов оборачивается единственным корневым NavigationContainer.
  • Stack работает по принципу стека (LIFO): новый экран кладётся поверх, goBack() снимает верхний. Используется для иерархии «список → детали».
  • Tab показывает равноправные разделы с панелью внизу. Переключение вкладок не образует истории «вперёд/назад».
  • В каждый экран приходят объекты navigation (для переходов) и route (имя маршрута и параметры).
  • Параметры передаются вторым аргументом: navigation.navigate('Details', { id }), читаются как route.params. Передавайте минимум данных (обычно id), они должны быть сериализуемыми.

Задание

Соберите приложение из 3–4 экранов: список Home → деталь Details (через Stack с передачей параметра), плюс нижние вкладки Home / Профиль / Настройки.

Шаг 1. Создание проекта и установка зависимостей

Окно терминала
npx create-expo-app@latest nav-app --template blank
cd nav-app
# Ядро React Navigation
npm install @react-navigation/native
# Обязательные нативные зависимости (через expo install)
npx expo install react-native-screens react-native-safe-area-context
# Навигаторы
npm install @react-navigation/native-stack
npm install @react-navigation/bottom-tabs

Шаг 2. Экран списка (Home) с переходом и параметром

Создайте src/screens/HomeScreen.js. Список рендерим через FlatList, по нажатию переходим на Details, передавая id и title.

import { View, Text, FlatList, Pressable, StyleSheet } from 'react-native';
const DATA = [
{ id: 1, title: 'React Native' },
{ id: 2, title: 'Expo' },
{ id: 3, title: 'Навигация' },
];
export default function HomeScreen({ navigation }) {
return (
<FlatList
data={DATA}
keyExtractor={(item) => String(item.id)}
renderItem={({ item }) => (
<Pressable
style={styles.row}
onPress={() =>
navigation.navigate('Details', { id: item.id, title: item.title })
}
>
<Text style={styles.text}>{item.title}</Text>
</Pressable>
)}
/>
);
}
const styles = StyleSheet.create({
row: { padding: 16, borderBottomWidth: 1, borderColor: '#eee' },
text: { fontSize: 18 },
});

Шаг 3. Экран детали (Details): чтение route.params и кнопка «Назад»

Создайте src/screens/DetailsScreen.js. Читаем параметры через route.params (со значениями по умолчанию на случай открытия без них).

import { View, Text, Button, StyleSheet } from 'react-native';
export default function DetailsScreen({ route, navigation }) {
const { id = 0, title = 'Без названия' } = route.params ?? {};
return (
<View style={styles.container}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.id}>Идентификатор: #{id}</Text>
<Button title="Назад" onPress={() => navigation.goBack()} />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12 },
title: { fontSize: 22, fontWeight: '600' },
id: { fontSize: 16, color: '#666' },
});

Шаг 4. Экраны «Профиль» и «Настройки»

Создайте простые src/screens/ProfileScreen.js и src/screens/SettingsScreen.js:

import { View, Text, StyleSheet } from 'react-native';
export default function ProfileScreen() {
return (
<View style={styles.center}>
<Text style={styles.text}>Профиль пользователя</Text>
</View>
);
}
const styles = StyleSheet.create({
center: { flex: 1, alignItems: 'center', justifyContent: 'center' },
text: { fontSize: 18 },
});

SettingsScreen.js сделайте по аналогии с текстом «Настройки».

Шаг 5. Stack-навигатор для вкладки Home

Вкладка Home — это не один экран, а стек (Home → Details). Создайте src/navigation/HomeStack.js:

import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from '../screens/HomeScreen';
import DetailsScreen from '../screens/DetailsScreen';
const Stack = createNativeStackNavigator();
export default function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Список' }}
/>
<Stack.Screen
name="Details"
component={DetailsScreen}
options={{ title: 'Детали' }}
/>
</Stack.Navigator>
);
}

Шаг 6. Tab-навигатор и корневой контейнер

В App.js собираем нижние вкладки и вкладываем стек в первую вкладку. У вкладки со стеком прячем заголовок таба (headerShown: false), чтобы не было двух заголовков.

import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeStack from './src/navigation/HomeStack';
import ProfileScreen from './src/screens/ProfileScreen';
import SettingsScreen from './src/screens/SettingsScreen';
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator screenOptions={{ tabBarActiveTintColor: '#2563eb' }}>
<Tab.Screen
name="HomeTab"
component={HomeStack}
options={{ title: 'Главная', headerShown: false }}
/>
<Tab.Screen
name="Profile"
component={ProfileScreen}
options={{ title: 'Профиль' }}
/>
<Tab.Screen
name="Settings"
component={SettingsScreen}
options={{ title: 'Настройки' }}
/>
</Tab.Navigator>
</NavigationContainer>
);
}

Запустите проект (npx expo start) и проверьте: список открывает детали с правильным id, кнопка «Назад» возвращает в список, нижние вкладки переключаются.

Шаг 7 (дополнительно). Передача данных обратно на предыдущий экран

Добавьте на экран Details кнопку «Отметить как избранное», которая возвращает результат обратно на Home:

// В DetailsScreen — вернуть данные обратно на экран Home
<Button
title="В избранное"
onPress={() => navigation.navigate('Home', { favoriteId: id })}
/>
// В HomeScreen — прочитать результат и среагировать
import { useEffect } from 'react';
useEffect(() => {
if (route.params?.favoriteId) {
console.log('Добавлено в избранное:', route.params.favoriteId);
}
}, [route.params?.favoriteId]);

Не забудьте добавить route в props HomeScreen ({ navigation, route }).


Критерии оценки

  • 20% — проект запускается, установлены @react-navigation/native, native-stack, bottom-tabs и нативные зависимости.
  • 20% — корректно настроены NavigationContainer и Tab-навигатор с тремя вкладками (Home, Профиль, Настройки).
  • 25% — Stack-навигатор Home → Details работает, переход выполняется через navigation.navigate.
  • 20% — параметр (id/имя) передаётся и корректно читается через route.params; работает кнопка «Назад».
  • 10% — Stack корректно вложен внутрь вкладки (без задвоения заголовков).
  • 5% — выполнено дополнительное задание (возврат данных на предыдущий экран).

Вопросы для самопроверки

  1. Зачем нужен NavigationContainer и почему он должен быть один на приложение?
  2. Чем модель Stack отличается от модели Tab? В каком случае какой использовать?
  3. Как передать параметр на следующий экран и как его прочитать на целевом экране?
  4. Что произойдёт, если экран Details открыть без параметров? Как от этого защититься?
  5. В чём разница между navigation.navigate и navigation.goBack?
  6. Зачем при вложении Stack во вкладку отключают headerShown у таба?
  7. Какими способами можно вернуть данные с дочернего экрана на предыдущий?

Ресурсы