如何在同一组件中定义多种类型的导航容器?
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 导航到任何屏幕
我是 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 导航到任何屏幕