Урок 06

Вложенные навигаторы

Реальные приложения комбинируют несколько навигаторов: стек внутри таба, drawer со стеком, модалки поверх всего.

Структура

RootStack
├── Tabs (BottomTab)
│   ├── Feed (Stack)
│   │   ├── FeedList
│   │   └── PostDetails
│   ├── Search
│   └── Profile (Stack)
│       ├── ProfileView
│       └── Settings
├── Modal
└── Auth (Stack)

Реализация

const RootStack = createNativeStackNavigator<RootStackParamList>();
const Tab = createBottomTabNavigator<TabParamList>();
const FeedStack = createNativeStackNavigator<FeedStackParamList>();

function FeedNavigator() {
    return (
        <FeedStack.Navigator>
            <FeedStack.Screen name="FeedList" component={FeedListScreen} />
            <FeedStack.Screen name="PostDetails" component={PostDetailsScreen} />
        </FeedStack.Navigator>
    );
}

function TabNavigator() {
    return (
        <Tab.Navigator>
            <Tab.Screen name="Feed" component={FeedNavigator} />
            <Tab.Screen name="Search" component={SearchScreen} />
            <Tab.Screen name="Profile" component={ProfileScreen} />
        </Tab.Navigator>
    );
}

export default function RootNavigator() {
    return (
        <RootStack.Navigator screenOptions={{ headerShown: false }}>
            <RootStack.Screen name="Tabs" component={TabNavigator} />
            <RootStack.Screen name="Modal" component={ModalScreen} options={{ presentation: 'modal' }} />
        </RootStack.Navigator>
    );
}

Типизация

export type FeedStackParamList = {
    FeedList: undefined;
    PostDetails: { id: number };
};

export type TabParamList = {
    Feed: NavigatorScreenParams<FeedStackParamList>;
    Search: undefined;
    Profile: undefined;
};

export type RootStackParamList = {
    Tabs: NavigatorScreenParams<TabParamList>;
    Modal: undefined;
};

NavigatorScreenParams позволяет передавать параметры вложенных экранов.

Навигация во вложенный

Из RootStack перейти на PostDetails внутри FeedStack:

navigation.navigate('Tabs', {
    screen: 'Feed',
    params: {
        screen: 'PostDetails',
        params: { id: 5 },
    },
});

useNavigation с типами

На экране внутри стека:

const navigation = useNavigation<NativeStackNavigationProp<FeedStackParamList>>();
navigation.navigate('PostDetails', { id: 5 });

На экране в корне:

const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
navigation.navigate('Modal');

getParent

Из вложенного выйти на родительский:

navigation.getParent()?.navigate('Modal');

Или с типами:

const parent = navigation.getParent<NativeStackNavigationProp<RootStackParamList>>();
parent?.navigate('Modal');

Модалки

Модалка на уровне корневого стека:

<RootStack.Screen
    name="ImagePreview"
    component={ImagePreview}
    options={{
        presentation: 'transparentModal',
        animation: 'fade',
        headerShown: false,
    }}
/>

Итоги

  • Реальные приложения — комбинация навигаторов
  • NavigatorScreenParams для вложенных
  • navigate('Tabs', { screen: 'Feed', params: {...} })
  • getParent для родителя
  • Модалки на корневом стеке