Урок 03

Stack Navigator

Стек экранов — базовый тип навигации. Экраны укладываются друг на друга.

Создание

import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator<RootStackParamList>();

<Stack.Navigator>
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>

Переход

function HomeScreen({ navigation }: { navigation: NativeStackNavigationProp<RootStackParamList> }) {
    return (
        <Pressable onPress={() => navigation.navigate('Details', { id: 5 })}>
            <Text>Открыть детали</Text>
        </Pressable>
    );
}

Или через useNavigation:

const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();

Параметры

На экране:

function DetailsScreen({ route }: { route: RouteProp<RootStackParamList, 'Details'> }) {
    const { id } = route.params;
    return <Text>ID: {id}</Text>;
}

Или useRoute:

const route = useRoute<RouteProp<RootStackParamList, 'Details'>>();
const { id } = route.params;

Методы навигации

navigation.navigate('Details', { id: 5 });  // переход, если экран есть — вернуться
navigation.push('Details', { id: 5 });      // всегда новый экран
navigation.replace('Login');                // заменить текущий
navigation.goBack();                        // назад
navigation.popToTop();                      // к первому
navigation.pop(2);                          // на 2 назад

Навигация из компонента

function BackButton() {
    const navigation = useNavigation();
    return (
        <Pressable onPress={() => navigation.goBack()}>
            <Text>Назад</Text>
        </Pressable>
    );
}

useNavigation даёт доступ к навигации без пропсов.

Хедер

<Stack.Screen
    name="Details"
    component={DetailsScreen}
    options={{
        title: 'Детали',
        headerBackTitle: 'Назад',
        headerTransparent: true,
        headerBlurEffect: 'light',
        headerLargeTitle: true,
        headerSearchBarOptions: {
            placeholder: 'Поиск',
            onChangeText: (e) => console.log(e.nativeEvent.text),
        },
    }}
/>

Динамический хедер

function DetailsScreen() {
    const { id } = useRoute().params;
    const navigation = useNavigation();

    useLayoutEffect(() => {
        navigation.setOptions({
            title: `Пост ${id}`,
            headerRight: () => (
                <Pressable onPress={() => share(id)}>
                    <Ionicons name="share" size={24} />
                </Pressable>
            ),
        });
    }, [id]);

    return <View />;
}

Анимация перехода

<Stack.Screen
    name="Modal"
    component={ModalScreen}
    options={{
        presentation: 'modal',      // 'card', 'modal', 'transparentModal', 'fullScreenModal'
        animation: 'slide_from_bottom', // 'default', 'slide_from_right', 'slide_from_left', 'fade', 'none'
    }}
/>

Жесты

options={{
    gestureEnabled: true,
    fullScreenGestureEnabled: true,
}}

Свайп слева направо на iOS — назад.

Итоги

  • Stack.Navigator + Stack.Screen
  • navigate, push, replace, goBack
  • Параметры через route.params
  • useLayoutEffect для динамического хедера
  • presentation для модалок