How do I nest my tab navigator with my stack navigator in react native? - react-native

Good evening,
I successfully created a project inside react native now I would like to nest my tab navigator with my stack navigator. I'm getting errors when I put my tab navigator with the stack navigator. My tab navigation code is:
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Earnings" component={EarningsScreen} />
</Tab.Navigator>
);
}
function Root() {
return (
<NavigationContainer>
<MyTabs/>
</NavigationContainer>
);
My stack navigator code is:
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Notifications" component={NotificationsScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}

It looks like you're using two separate NavigationContainers, and you're not nesting the navigators at all; the code for each is completely separate.
Given that your question is about needing the tabs within the stack, try this instead:
delete the Root component (you should only have one NavigationContainer in your app)
use the MyTabs component as one of your stack screens
Example:
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Earnings" component={EarningsScreen} />
</Tab.Navigator>
);
}
function MyStack() {
return (
<Stack.Navigator>
{/* Tabs are inserted here */}
<Stack.Screen name="Tabs" component={MyTabs} />
<Stack.Screen name="Notifications" component={NotificationsScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}

Related

React Navigation - Drawer inside Stack go back

Taking this example for the official documentation :
function Root() {
return (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Drawer.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Root"
component={Root}
options={{ headerShown: false }}
/>
<Stack.Screen name="Feed" component={Feed} />
</Stack.Navigator>
</NavigationContainer>
);
}
They just explain here how to navigate to the Profile screen from the Feed screen like this :
navigation.navigate('Root', { screen: 'Profile' });
I would to know how can I navigate to the Feed screen from the Profile screen;
You can just use the navigation object and its navigate function since the Feed screen is nested inside the same navigator as the Root stack.
Destructure the navigation object from the props of Profile.
function Profile({navigation}) {
return ...
}
Now, just use the navigation object as follows in order to navigate to Feed.
navigation.navigate("Feed")

Use DrawerNavigator and StackNavigator together [duplicate]

This is my tab navigator:
<Tab.Navigator initialRouteName="Home" backBehavior="initialRoute">
<Tab.Screen
name="Science"
component={Science}
options={{
tabBarLabel: 'Science',
tabBarIcon: ({color, size}) => (
<Image source={require('../../assets/images/science-tab.png')} />
),
}}
/>
<Tab.Screen name="Dashboard" component={Dashboard} />
</Tab.Navigator>
This is DrawerNavigator:
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
And this is my root navigator: Below Bottomnavigation is the tab navigator.
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="BottomNavigation"
component={BottomNavigation}
options={{title: this.createTitle()}}
/>
</Stack.Navigator>
</NavigationContainer>
I recommend you to make your TabNavigator a screen of DrawerNavigator
You can do something like this:
function TabNavigator({navigation}) {
return (
<Tab.Navigator>
// Your tab screens
</Tab.Navigator>
);
}
function DrawerNavigator() {
return (
<Drawer.Navigator>
<Drawer.Screen name="TabNavigator" component={TabNavigator} />
</Drawer.Navigator>
);
}
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="DrawerNavigator" component={DrawerNavigator} />
</Stack.Navigator>
</NavigationContainer>
);
};
If you want to open your drawer, you can call navigation.openDrawer() in your TabNavigator.
Update to address label issue
You can create a drawer content component to override the default behavior of adding the DrawerNavigator screens' labels as the content of the drawer.
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
/>
// ...
</DrawerContentScrollView>
);
}
Then you need to change the DrawerNavigator to this:
function DrawerNavigator({route}) {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="TabNavigator" component={TabNavigator} />
<Drawer.Screen name="Home" component={Home} />
</Drawer.Navigator>
);
}
So you can add new screens to your DrawerNavigator and navigate to them using the DrawerItem onPress function.
Of course make sure to import DrawerContentScrollView, DrawerItemList and DrawerItem from #react-navigation/drawer.
For more info look at: https://reactnavigation.org/docs/drawer-navigator/#providing-a-custom-drawercontent.

React Native Tab Navigator within Stack Navigator

I have the following Stack Navigator in App.js:
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Login" screenOptions={{headerShown:false}}>
{user ? (
<>
<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={user} />}
</Stack.Screen>
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
);
I want to add a bottom tab navigator that shows up on the HomeScreen, and allows me to go back and forth between the HomeScreen and ProfileScreen. How can this be done?
The way to do this is to create a tab navigator component where Home and Profile are 2 screens of the navigator:
const Tab = createBottomTabNavigator();
function TabNavigator({route}) {
// Retrieve user from initalParams.
// The user is passed to initialParams in the snippet below.
const user = route.params?.user
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
Then the tab navigator can be a screen of your stack navigator:
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Login"
screenOptions={{headerShown: false}}>
{user ? (
<>
<Stack.Screen name="Tabs" component={TabNavigator} initialParams={{user: user}}/>
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
);
If you need access to user from inside HomeScreen you can pass it using down using initialParams the same way it was passed down to the TabNavigator. If you don't want to keep passing stuff down like this you could try the Context api.
I removed the Login screen in the above example, because I assumed this was a mistake as you already have a Login screen defined for when you don't have an authenticated user.

How to use drawer navigator and tab navigator simultaneously?

This is my tab navigator:
<Tab.Navigator initialRouteName="Home" backBehavior="initialRoute">
<Tab.Screen
name="Science"
component={Science}
options={{
tabBarLabel: 'Science',
tabBarIcon: ({color, size}) => (
<Image source={require('../../assets/images/science-tab.png')} />
),
}}
/>
<Tab.Screen name="Dashboard" component={Dashboard} />
</Tab.Navigator>
This is DrawerNavigator:
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
And this is my root navigator: Below Bottomnavigation is the tab navigator.
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="BottomNavigation"
component={BottomNavigation}
options={{title: this.createTitle()}}
/>
</Stack.Navigator>
</NavigationContainer>
I recommend you to make your TabNavigator a screen of DrawerNavigator
You can do something like this:
function TabNavigator({navigation}) {
return (
<Tab.Navigator>
// Your tab screens
</Tab.Navigator>
);
}
function DrawerNavigator() {
return (
<Drawer.Navigator>
<Drawer.Screen name="TabNavigator" component={TabNavigator} />
</Drawer.Navigator>
);
}
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="DrawerNavigator" component={DrawerNavigator} />
</Stack.Navigator>
</NavigationContainer>
);
};
If you want to open your drawer, you can call navigation.openDrawer() in your TabNavigator.
Update to address label issue
You can create a drawer content component to override the default behavior of adding the DrawerNavigator screens' labels as the content of the drawer.
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
/>
// ...
</DrawerContentScrollView>
);
}
Then you need to change the DrawerNavigator to this:
function DrawerNavigator({route}) {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="TabNavigator" component={TabNavigator} />
<Drawer.Screen name="Home" component={Home} />
</Drawer.Navigator>
);
}
So you can add new screens to your DrawerNavigator and navigate to them using the DrawerItem onPress function.
Of course make sure to import DrawerContentScrollView, DrawerItemList and DrawerItem from #react-navigation/drawer.
For more info look at: https://reactnavigation.org/docs/drawer-navigator/#providing-a-custom-drawercontent.

ReactNative- Tab Navigator Inside Stack Navigator

Need to Show Tabs For Home Module after Signup Module
using React-navigation
Working Code with Only Stack Screens
const Stack = createStackNavigator();
const Bottom = createBottomTabNavigator();
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
<Stack.Screen name="Welcome" component={WelcomeScreen}
options={{
title: '',
headerBackTitleVisible: false,
headerBackTitle: '',
headerShown: true
}}
/>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Need to show Tab from SigninScreen Button
Tab 1: Dashboard:
Tab 2: Profile
Tried Code:
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
Now I need to combine these two block of codes so I can navigate to Tabs
Tab screen will have further navigations
The idea would be to wrap the tabs screen inside component and add it to the stack conditionally.
const HomeScreen = () =>{
return (
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
);
}
Your stack should change as below
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
{
this.state.isSignedIn ? (
<>
<Stack.Screen name="Welcome" component={WelcomeScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</>
) : (
<>
<Stack.Screen name="ResetPassword" component={HomeScreen} />
</>
)
}
</Stack.Navigator>
</NavigationContainer>
);
}
IsSignedIn can be the state variable or a variable that you store the logged in status
You can refer the authentication flows
https://reactnavigation.org/docs/auth-flow