I'm using RN navigation v5 for my app and I'm gonna build my navigation like image below:
as you can see this app has an intro then some authentication screens and after sign in user view the home screen. so what I want is stack for intro, drawer and bottom tab navigation for my home screen. you can see my code below:
const IntroStack = createStackNavigator();
const IntroNavigation = () => {
return (
<NavigationContainer>
<IntroStack.Navigator>
<IntroStack.Screen name='intro' component={Intro} options={{ headerShown: false }} />
<IntroStack.Screen name='login' component={Login} options={{ headerShown: false }} />
<IntroStack.Screen name='createAccount' component={CreateAccount} options={{ headerShown: false }} />
<IntroStack.Screen name='forgotPassword' component={ForgotPassword} options={{ headerShown: false }} />
<IntroStack.Screen name='enterCode' component={EnterCode} options={{ headerShown: false }} />
<IntroStack.Screen name='changePassword' component={ChangePassword} options={{ headerShown: false }} />
<IntroStack.Screen name='home' component={Home} options={{ headerShown: false }} />
</IntroStack.Navigator>
</NavigationContainer>
)
}
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
const TabNavigation = () => {
return (
<Tab.Navigator>
<Tab.Screen name="home" component={Home} />
<Tab.Screen name="worldTour" component={WorldTour} />
<Tab.Screen name="Outlet" component={Outlet} />
<Tab.Screen name="Profile" component={Profile} />
<Tab.Screen name="OutTherapists" component={OurTherapists} />
</Tab.Navigator>
);
}
const DrawerNavigation = () => {
const dimentions = useWindowDimensions();
return (
<Drawer.Navigator drawerStyle={{ width: dimentions.width }} drawerContent={props => <DrawerContent />}>
<Drawer.Screen name="home" component={IntroNavigation} />
</Drawer.Navigator>
);
}
export default TabNavigation;
but this did not work. I tried to read docs and watch some tutorials but I couldn't find something similar. I know somehow I must nest this stacks to each other but none of my tried ways achieve what I want. any help would be appreciated.
const IntroNavigation = () => {
return (
<NavigationContainer>
<IntroStack.Navigator>
<IntroStack.Screen name='intro' component={Intro} options={{ headerShown: false }} />
<IntroStack.Screen name='login' component={Login} options={{ headerShown: false }} />
<IntroStack.Screen name='createAccount' component={CreateAccount} options={{ headerShown: false }} />
<IntroStack.Screen name='forgotPassword' component={ForgotPassword} options={{ headerShown: false }} />
<IntroStack.Screen name='enterCode' component={EnterCode} options={{ headerShown: false }} />
<IntroStack.Screen name='changePassword' component={ChangePassword} options={{ headerShown: false }} />
<IntroStack.Screen name='home' component={DrawerNavigation} options={{ headerShown: false }} />
</IntroStack.Navigator>
</NavigationContainer>
)
}
const Drawer = createDrawerNavigator();
const DrawerNavigation = () => {
const dimentions = useWindowDimensions();
return (
<Drawer.Navigator drawerStyle={{ width: dimentions.width }} drawerContent={props => <DrawerContent />}>
<Drawer.Screen name="Home" component={TabNavigation} />
</Drawer.Navigator>
);
}
const Tab = createBottomTabNavigator();
const TabNavigation = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="WorldTour" component={WorldTour} />
<Tab.Screen name="Outlet" component={Outlet} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
);
}
export default IntroNavigation;
Your structure should be like that for Tabs:
<Tab.Navigator>
<Tab.Screen name="home" component={DrawerStack} />
<Tab.Screen name="worldTour" component={WorldTour} />
<Tab.Screen name="Outlet" component={Outlet} />
<Tab.Screen name="Profile" component={Profile} />
<Tab.Screen name="OutTherapists" component={OurTherapists} />
</Tab.Navigator>
You should use this tab navigator as screen in main stack navigator like this:
<NavigationContainer>
<IntroStack.Navigator>
<IntroStack.Screen name='intro' component={Intro} options={{ headerShown: false }} />
<IntroStack.Screen name='login' component={Login} options={{ headerShown: false }} />
<IntroStack.Screen name='createAccount' component={CreateAccount} options={{ headerShown: false }} />
<IntroStack.Screen name='forgotPassword' component={ForgotPassword} options={{ headerShown: false }} />
<IntroStack.Screen name='enterCode' component={EnterCode} options={{ headerShown: false }} />
<IntroStack.Screen name='changePassword' component={ChangePassword} options={{ headerShown: false }} />
<IntroStack.Screen name='Tabs' component={Tabs} options={{ headerShown: false }} />
</IntroStack.Navigator>
</NavigationContainer>
In addition, the name of the screen should not be same as you have 'home' screen in each navigator, this will cause conflict when navigating from navigation ref.
For signup flow, you can follow this procedure:
https://reactnavigation.org/docs/upgrading-from-4.x/#switch-navigator
Related
I am creating a react native app in which, I am using the react-native-linear-gradient. I want to use the linear gradient on all of my screens. So I tried to wrap my navigation container(react navigation 6) but it is not working, when applying linear gradient to individual screens then it is showing.
const SignupNavigation = () => {
return (
<Provider store={store}>
<NavigationContainer>
<LinearGradient
colors={['#05086A', '#0B023A']}
style={[GlobalStyle.rootScreen]}>
<SafeAreaView style={GlobalStyle.rootScreen}>
<Stack.Navigator>
<Stack.Screen
name="Start"
component={StartScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="SendOtp"
component={SendOtpScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="VerifyOtp"
component={VerfiyOtpScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="VerifiedOtp"
component={VerifiedOtpScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="SignUpUserInfo"
component={SignUpUserInfoScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="SignUpGameSelection"
component={SignUpGameSelectScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="SignUpGameTags"
component={SignUpGameTagScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="TabNavigation"
component={TabNavigation}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</SafeAreaView>
</LinearGradient>
</NavigationContainer>
</Provider>
);
};
export default SignupNavigation;
style for rootscreen:
rootScreen: {
flex: 1,
},
I want to reduce the repetited code such as implementing safeAreaView and linear-gradient to every screen.
Please guide me what is the fix?
Thanks in advance.
I need to hide nav bar on top in specific screens. How to achieve?. i am using react-navigation/material-top-tabs
I need to hide nav bar on top in specific screens. How to achieve?. i am using react-navigation/material-top-tabs
I need to hide nav bar on top in specific screens. How to achieve?. i am using react-navigation/material-top-tabs
//page 1 <Stack.Navigator headerMode="none" initialRouteName="Connection">
<Stack.Screen
name="Connection"
component={UserScreen}
options={{ unmountOnBlur: true }}
/>
</Stack.Navigator>
//page2 <Tab.Navigator
// screenOptions={{ tabBarVisible: false }}
// screenOptions={({ route }) => ({
// tabBarVisible: false,
// })}
initialRouteName="UserTabStack"
tabBarOptions={{
labelStyle: {
fontWeight: "bold",
},
indicatorStyle: {
backgroundColor: "black",
},
}}
>
<Tab.Screen
name="UserTabStack"
// component={UserList}
component={UserTabStack}
options={{ tabBarLabel: "Userlist" }}
listeners={({ route }) => {
setTabPage(route.name);
}}
/>
<Tab.Screen
name="GroupList"
// component={GroupList}
component={GroupTabStack}
options={{ tabBarLabel: "GroupList" }}
listeners={({ route }) => {
setTabPage(route.name);
}}
/>
</Tab.Navigator> //page3 <Stack.Navigator headerMode="none" initialRouteName="UserList">
<Stack.Screen
name="UserList"
component={UserList}
options={{ unmountOnBlur: true }}
/>
<Stack.Screen
name="AddConnection"
component={AddUserScreen}
options={{ unmountOnBlur: true }}
/>
<Stack.Screen
name="Chat"
component={ChatScreen}
options={{ unmountOnBlur: true }}
/>
</Stack.Navigator>
set headerShown to false in Stack.Screen options
<Stack.Screen
name="UserList"
component={UserList}
options={{ unmountOnBlur: true, headerShown: false }}
/>
Per the React Navigation Docs, you can hide the tab bar on specific screens by changing your navigation structure. In their example:
function HomeTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Notifications" component={Notifications} />
</Tab.Navigator>
);
}
function App() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeTabs} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
);
}
The tab navigator is inside the first screen, and is the first component in your app's navigator. The following components are the two components that you don't want the top bar to be shown on, so in this example, Settings and Profile.
I want a user to log in BEFORE they are taken to the "Home" screen. Once they hit the home screen, the tabs are shown. I do not want to show the tabs during login/signup.
Here is what I have so far:
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
const Switch = createSwitchNavigator();
const AppContainer = createAppContainer();
function AuthNavigation() {
return (
<Stack.Navigator headerMode="none" initialRouteName="Login">
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Signup" component={Signup} />
</Stack.Navigator>
)
}
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Home"
activeColor="#161F3D"
inactiveColor="#B8BBC4">
<Tab.Screen
name="Home"
component={Home}
// options={{
// tabBarIcon: <Icon name="home" size={24} />
// }}
/>
<Tab.Screen
name="Leaderboard"
component={Leaderboard}
// options={{
// tabBarIcon: <Icon name="trophy" size={24} />
// }}
/>
<Tab.Screen
name="Create"
component={Create}
// options={{
// tabBarIcon: <Icon name="add" size={40} />
// }}
/>
<Tab.Screen
name="Notifications"
component={Notification}
// options={{
// tabBarIcon: <Icon name="notifications-circle-outline" size={24} />
// }}
/>
<Tab.Screen
name="Profile"
component={Profile}
// options={{
// tabBarIcon: <Icon name="person" size={24} />
// }}
/>
</Tab.Navigator>
);
}
export default function App() {
return (
<AppContainer>
<Switch.Navigator headerMode="none" initialRouteName="Auth">
<Switch.Screen name="Auth" component={AuthNavigation()} />
<Switch.Screen name="Tabs" component={MyTabs()} />
</Switch.Navigator>
</AppContainer>
);
}
This results in the following error:
TypeError: undefined is not an object (evaluating 'Object.keys(routeConfigs)')
How can I build these two navigators so the auth and the tab navigators are separate?
You only need to pass the reference of the component. You don't need to execute it. It should look like this -
<Switch.Screen name="Auth" component={AuthNavigation} />
<Switch.Screen name="Tabs" component={MyTabs} />
how do I remove the header on createMaterialTopTabNavigator()?
I've looked everywhere, including the documentation. So far I've only seen examples
which are relevant to the previous version.
Here's my code:
<NavigationContainer headerMode='none'>
<Tab.Navigator options={{ headerShown: false }}>
<Tab.Screen name="Home" component={Home}/>
<Tab.Screen name="Settings" component={Settings}/>
</Tab.Navigator>
</NavigationContainer>
EDITED
HeaderShown option is for screens, not navigator. So replace by this
const IndexStack = createStackNavigator()
const index = () => {
return(
<IndexStack.Navigator initialRouteName="tabNav">
<IndexStack.Screen name="tabNav" options={{ headerShown: false }} component={tabNav} />
</IndexStack.Navigator>
)
}
const tabNav = () => {
return(
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Settings" component={Settings} />
</Tab.Navigator>
</NavigationContainer>
)
}
I have 3 screen in my app: "Home, Contacts, Profile". I created a custom header to show in Home and Contacts, but not in Profile screen. The problem is: my custom header don't hide in Profile Screen. If I remove my custm header to use the default header, it hides, but when I back to my custom header this doesn't happen.
App.js
<NavigationContainer ref={navigationRef}>
<Stack.Navigator
headerMode="float"
initialRouteName="Home"
screenOptions={{
header: props => <CustomHeader {...props} />
}}>
<Stack.Screen
name="Home"
component={Home}
options={{
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS
}}/>
<Stack.Screen name="Contacts" component={Contacts}
options={{
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS
}}/>
<Stack.Screen
name="Profile"
component={Profile}
options={{
headerShown: false
}} />
</Stack.Navigator>
</NavigationContainer>
You can provide screen wise header like.
<NavigationContainer ref={navigationRef}>
<Stack.Navigator
headerMode="float"
initialRouteName="Home">
<Stack.Screen
name="Home"
component={Home}
options={{
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
header: (props) => <CustomHeader {...props} />
}}
/>
<Stack.Screen
name="Contacts"
component={Contacts}
options={{
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
header: (props) => <CustomHeader {...props} />
}}
/>
<Stack.Screen
name="Profile"
component={Profile}
options={{
headerShown: false,
header: null,
}}
/>
</Stack.Navigator>
</NavigationContainer>;
Or you can create custom function for all header
function getHeader(route, props) {
const routeName = route.state
?
route.state.routes[route.state.index].name
: || 'Home';
switch (routeName) {
case 'Home':
case 'Contacts':
return <CustomHeader {...props} />
case 'Profile':
return null;
}
}
and use it like
<Stack.Screen
name="Profile"
component={Profile}
options={({ route }) => ({
header: (props)=> getHeader(route, props),
})}
/>
Source : https://reactnavigation.org/docs/screen-options-resolution