如何在同一组件中定义多种类型的导航容器?

How do I define multiple types of navigation containers in the same component?

我是 React Native 的新手,所以我需要帮助构建我的导航页面。我希望我的应用程序具有类似 instagram 的结构——主页应该是 createBottomTabNavigator 从那里我有几个不同的页面,我可以轻松地在它们之间切换。这是我的代码:

export default const MyTabs = ({ currentUser, navigation }) => {
  return (
    <Tab.Navigator initialRouteName="Home">
      <Tab.Screen
        name="Home"
        component={HomeScreen}
      />
      <Tab.Screen
        name="Network"
        component={NetworkScreen}
      />
      <Tab.Screen
        name="Profile"
        component={ProfileScreen}
        options={{
          tabBarIcon: ({ color, size }) => (
            <Entypo name="map" color={color} size={26} />
          ),
        }}
      />
    </Tab.Navigator>
  );
};

然后在我的 App.js 文件中,我这样称呼它:

return (
      <Provider store={store}>
        <NavigationContainer>
          <MyTabs />
        </NavigationContainer>
      </Provider>
    );

上面的代码工作正常。问题是当我想执行更复杂的导航时。例如,在我的主页上有一个对象列表,有一次,我单击这些对象我想导航到一个新页面——使用 Stack 导航器。我该怎么做,我应该在哪里定义这个页面?我是在我的 Home 页面中还是在我的 App.js 页面中以某种方式定义它?在我看来应该是这样的:

<Stack.Screen
              name="Details"
              component={DetailScreen}
            />

我试着把它放在App.js里面,像这样:

<Provider store={store}>
  <NavigationContainer>
    <MyTabs />
    <Stack.Navigator>
      <Stack.Screen
        name="Meetup Details"
        component={MeetupDetails}
        options={{
          headerTitle: "Meetup Details",
        }}
      />
    </Stack.Navigator>
  </NavigationContainer>
</Provider>;

但是当然没用。

我还有另一个问题 - 在我的底部选项卡中,我可以导航到 My profile 屏幕并且工作正常。但我也想查看其他配置文件。所以我的底部选项卡是为我自己的个人资料保留的,但是我如何定义另一个 Profile 屏幕,它可以转到其他用户的个人资料?是否需要与堆栈导航器一起使用?是否需要再次在 App.js 中定义?是否可以在同一个页面定义两个不同的导航器(底部选项卡和堆栈)(Profile)?

通常,当您有一个底部标签导航器时,每个标签都是一个 StackNavigator

export default const MyTabs = ({ currentUser, navigation }) => {
  return (
    <Tab.Navigator initialRouteName="Home">
      <Tab.Screen
        name="Home" // here this would be BottomTabRoutes.HOME
        component={HomeNavigator}
      />
      <Tab.Screen
        name="Network"  // here this would be BottomTabRoutes.NETWORK
        component={NetworkNavigator}
      />
      <Tab.Screen
        name="Profile"  // here this would be BottomTabRoutes.PROFILE
        component={ProfileNavigator}
        options={{
          tabBarIcon: ({ color, size }) => (
            <Entypo name="map" color={color} size={26} />
          ),
        }}
      />
    </Tab.Navigator>
  );
};

然后您的 MeetupDetails 屏幕将包含在 HomeNavigator 中,这是一个 StackNavigator

export const HomeNavigator = () => {
  return (
    <Stack.Navigator
      screenOptions={{
       ...
      }}>
      <Stack.Screen
        name={HomeRoutes.HOME}
        component={Home}
        options={{
          headerStyle: styles.header,
          title: 'Home'
        }}
      />
       <Stack.Screen
        name={HomeRoutes.MEETUP_DETAILS}
        component={MeetupDetails}
        options={{
          headerStyle: styles.header,
          title: 'Meetup Details'
        }}
      />
    </Stack.Navigator>
    
  }

此外,我建议将你的路线名称存储在一个枚举中,这样会更容易,并且它们可能的路线道具在一个 tpye 中 像这样:

export enum BottomTabRoutes {
  HOME = 'Home',
  NETWORK = 'Network',
  PROFILE = 'Profile',
}

export type BottomTabRouteProps = {
  [BottomTabRoutes.HOME]: {title: string}; // this is another parameter example
  [BottomTabRoutes.PROFILE]: undefined;
  [BottomTabRoutes.NETWORK]: undefined;
};

每个 Stack Navigator 都一样:

export enum HomeRoutes = {
  HOME = 'Home',
  MEETUP_DETAILS = 'Meetup Details',
}


export type HomeRouteProps = {
  [HomeRoutes.HOME]: undefined
  [HomeRoutes.MEETUP_DETAILS: { someParamName: SomeType } // this might be a parameter you'll send through navigation
}

// Therefore, your MeetupDetails screen will look something like this: 

export const MeetupDetails = (props: StackScreenProps<HomeRouteProps, HomeRouteProps.MEETUP_DETAILS>,) => {
  
  const navigationParam = props.route.params.someParamName

  
  return (
    <View>
    ...
    
    </View>
    
    )
    
  }

编辑

关于Profile Screen,我相信你可以有这样的:

export const MainNavigator = () => {
  return (
    <Stack.Navigator screenOptions={{headerShown: false}}>
      <Stack.Screen name={MainNavigatorRoutes.HOME} component={HomeNavigator} />
      <Stack.Screen name={MainNavigatorRoutes.USER} component={UserNavigator} />
    </Stack.Navigator>
  );
};


export const UserNavigator = () => {
  return (
    <Stack.Navigator
      screenOptions={({navigation}) => ({
       ...)}>
      <Stack.Screen
        name={UserNavigatorRoutes.SOME_OTHER_SCREEN}
        component={UserSettings}
      />
      <Stack.Screen
        name={UserNavigatorRoutes.USER_PROFILE}
        component={UserProfile}
      />
    </Stack.Navigator>
  );
};


export const HomeNavigator = () => {
  return (
    <Stack.Navigator screenOptions={{title: ''}} >
     <Stack.Screen
          name={HomeNavigatorRoutes.HOME_TABS}
          component={HomeTabNavigator}
          options={{
            headerShown: false,
          }}
        />
    </Stack.Navigator>
  );
};

export const HomeTabNavigator = () => (
  <Stack.Navigator >
    <Stack.Screen
      name={HomeTabNavigatorRoutes.TAB_NAVIGATOR}
      component={MyTabs}
      options={{headerShown: false}}
    />
  </Stack.Navigator>

基本上,结构如下所示:MainNavigator = { HomeNavigator, UserNavigator }。这样,每个导航器都是独立的,即使您在 UserNavigator

的屏幕中,您也应该能够从 UserNavigator 导航到任何屏幕