Типизация маршрутов в Stack Navigator
Подготовка к работе: наш проект
Для этой лекции мы будем продолжать развивать наше мобильное приложение. Мы уже настроили Stack Navigator и создали два экрана: HomeScreen и DetailsScreen. Теперь наша задача — подключить передачу параметров между этими экранами с использованием React Navigation и типизации TypeScript.
Определяем структуру маршрутов с типами
Сначала нам нужно определить, какие параметры принимает каждый экран. Для этого мы создаём объект интерфейса, где ключи — это имена экранов, а значения — типы параметров.
type RootStackParamList = {
Home: undefined; // экран Home не принимает параметры
Details: { itemId: number; description?: string }; // экран Details принимает параметры
};
Здесь мы определяем два маршрута:
- "Home" не принимает никаких параметров, поэтому его тип —
undefined. - "Details" принимает два параметра:
itemId(обязательный, типnumber).description(необязательный, типstring).
Примечание: необязательные параметры типизируются с помощью ?, что позволяет передавать их факультативно.
Добавляем тип в Stack Navigator
Теперь передаём наш тип RootStackParamList в Stack Navigator. Это делается с использованием типа NativeStackScreenProps из React Navigation.
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator<RootStackParamList>();
Таким образом, Stack Navigator готов принимать типизированные маршруты.
Передача параметров между экранами
Давайте рассмотрим, как параметры отправляются с одного экрана на другой.
Отправка параметров из компонента HomeScreen
На экране HomeScreen мы создадим кнопку, которая будет отправлять параметры на DetailsScreen с использованием метода navigate.
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useNavigation } from '@react-navigation/native';
import { RootStackParamList } from './types'; // импортируем типы маршрутов
type HomeScreenNavigationProp = NativeStackNavigationProp<RootStackParamList, 'Home'>;
const HomeScreen: React.FC = () => {
const navigation = useNavigation<HomeScreenNavigationProp>();
const goToDetails = () => {
navigation.navigate('Details', {
itemId: 42,
description: 'Это описание передано с HomeScreen',
});
};
return (
<View>
<Text>Home Screen</Text>
<Button title="Перейти на Details" onPress={goToDetails} />
</View>
);
};
Вот что мы сделали:
- Использовали
useNavigationс типомHomeScreenNavigationProp, чтобы получить доступ к навигационным методам с типизацией. - Передали параметры
itemIdиdescriptionв методnavigate. TypeScript проверит, что переданные параметры соответствуют типу, указанному для экрана "Details".
Получение параметров на DetailsScreen
На экране DetailsScreen мы извлекаем переданные параметры с использованием хука useRoute.
import { RouteProp } from '@react-navigation/native';
import { RootStackParamList } from './types'; // импортируем типы маршрутов
type DetailsScreenRouteProp = RouteProp<RootStackParamList, 'Details'>;
const DetailsScreen: React.FC = () => {
const route = useRoute<DetailsScreenRouteProp>();
const { itemId, description } = route.params;
return (
<View>
<Text>Details Screen</Text>
<Text>ID: {itemId}</Text>
<Text>Description: {description || 'Описание отсутствует'}</Text>
</View>
);
};
Здесь мы использовали:
useRouteс типомDetailsScreenRouteProp, чтобы получить доступ к параметрам с типизацией.- Извлекли параметры
itemIdиdescriptionизroute.params. Еслиdescriptionотсутствует, отображаем текст "Описание отсутствует".
Что произойдёт, если передать лишние параметры?
TypeScript не позволит вам передать параметры, которые не указаны в типах маршрутов. Например, если вы попытаетесь добавить extraData, IDE сразу же подчеркнёт ошибку:
navigation.navigate('Details', {
itemId: 42,
description: 'Это описание',
extraData: 'Ошибка! Такого поля нет в типах',
});
Это помогает значительно сократить количество ошибок при разработке.
Типизация параметров по умолчанию
Иногда экран может принимать параметры по умолчанию. Можно определить их с помощью объекта defaultProps:
const DetailsScreen: React.FC = () => {
const route = useRoute<DetailsScreenRouteProp>();
const { itemId, description = 'Описание отсутствует' } = route.params;
return (
<View>
<Text>Details Screen</Text>
<Text>ID: {itemId}</Text>
<Text>Description: {description}</Text>
</View>
);
};
Теперь, даже если параметр description не передан, будет использовано значение "Описание отсутствует".
Работа с вложенными навигаторами
Если в приложении используются вложенные навигаторы (например, Stack внутри Tab Navigator), типизация становится немного сложнее. Нужно объединить типы маршрутов.
Пример:
type TabParamList = {
Dashboard: undefined;
Profile: undefined;
};
type RootStackParamList = {
Home: undefined;
Details: { itemId: number; description?: string };
Tabs: NavigatorScreenParams<TabParamList>;
};
Используйте NavigatorScreenParams для передачи параметров вложенного навигатора. Это обеспечит правильную типизацию при переходе к "Tabs".
Типичные ошибки и их решение
Опытный разработчик знает, что "где тонко, там и рвётся". Основные проблемы при типизации параметров включают:
- Неправильно указанные ключи экранов. Проверьте, что они совпадают с именами экранов в Stack Navigator.
- Ошибки при добавлении вложенных навигаторов. Используйте
NavigatorScreenParams, если задействуете вложенные навигаторы. - Проблемы с необязательными параметрами. Убедитесь, что указали
?для необязательных параметров.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ