Nesting StackNavigator inside BottomTabNavigator react-navigation v5 - javascript

Going through my first React Native project, using react-navigation v5, and struggling to work out the logic behind multiple navigators in one.
I've tried to copy the 'auth-flow' setup from here, but I have some extra requirements, where once signed in, it should render a bottomTab navigator with three items (create, lists, account) where the second screen lists, renders a list of items where clicking one opens a new screen for the details (where I'd imagine these two screens would be a stack?)
pseudo routes:
- home
- lists
- details <- nested in the tab navigator screen
- account
current setup:
export default function App() {
return (
<SafeAreaProvider>
<NavigationContainer>
{isSignedIn ? (
<Tab.Navigator>
<Tab.Screen name='List' component={TrackListScreen} />
<Tab.Screen name='Create' component={TrackCreateScreen} />
<Tab.Screen name='Account' component={AccountScreen} />
</Tab.Navigator>
) : (
<Stack.Navigator>
<Stack.Screen name='Signup' component={SignupScreen} />
<Stack.Screen name='Signin' component={SigninScreen} />
</Stack.Navigator>
)}
</NavigationContainer>
</SafeAreaProvider>
);
}

What you'll want to do is make the List tab it's own stack navigator. So you'll have this
export default function App() {
return (
<SafeAreaProvider>
<NavigationContainer>
{isSignedIn ? (
<Tab.Navigator initialRouteName='TrackListNavigator'>
<Tab.Screen name='TrackListNavigator' component={TrackListNavigator} />
<Tab.Screen name='Create' component={TrackCreateScreen} />
<Tab.Screen name='Account' component={AccountScreen} />
</Tab.Navigator>
) : (
<Stack.Navigator>
<Stack.Screen name='Signup' component={SignupScreen} />
<Stack.Screen name='Signin' component={SigninScreen} />
</Stack.Navigator>
)}
</NavigationContainer>
</SafeAreaProvider>
);
}
So then instead of the tab navigating to TrackListScreen, it instead navigates to a new stack navigator that contains that screen like this
export default function TrackListNavigator() {
return (
<Stack.Navigator initialRouteName='TrackListScreen'>
<Stack.Screen name='TrackListScreen' component={TrackListScreen} />
</Stack.Navigator>
)
}
This way, when you are not signed in you will only have access to the Signup and Signin screens. Then once signed in you will land on the TrackListScreen with access to any other Stack.Screen you add to the TrackListNavigator.

You would in this scenario create an extra holding component, such as TrackListHome. TrackListHome would be a component that is specifically a StackNavigator, with the initialRouteName being your TrackListScreen, and Details would be another Screen in your StackNavigator. Then you would be able to call
props.navigation.navigate("TrackListDetail")
Your StackNavigator might look like this (TrackListHome)
return (
<Stack.Navigator initialRouteName={'TrackListScreen'}>
<Stack.Screen name='TrackListScreen' component={TrackListScreen} />
<Stack.Screen name='TrackListDetail' component={TrackListDetail} />
</Stack.Navigator>)
Then inside of your TabNavigation you would use this TrackListHome component.

Related

React Navigation Nested Tab.Navigator - Show InitialRoute not in Tabs

Using React-Navigation in my app, I want the initialRoute to be the "Home" component with the BottomTabNavigator shown. But I do not want Home to be one of the tabs. Adding initialRouteName="Home" shows Home as the initial route but does not show the tabs. Without initialRoute I get the tabs but not the Home Screen as the initial.
I have a nested React Navigation set up like this:
const MyTabs = () =>{
return (
<Tab.Navigator>
<Tab.Screen name="About" component={AboutStack} />
<Tab.Screen name="Setting" component={SettingStack} />
</Tab.Navigator>
);
}
const MyStack = () => {
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Tabs" component={MyTabs} />
<Stack.Screen name="Home" component={HomeStack} />
</Stack.Navigator>
);
}
This seems like it should be relatively simple to implement, but I've searched far and wide for another similar question and I've tried a number of different nesting setups to no avail.
Running: "#react-navigation/stack": "^6.0.7", or "latest"
Here is a snack of the full test code: https://snack.expo.dev/#dezpo/nestednavigator_homepage_notintab
Any help greatly appreciated.
You can set the initial route in the MyStack navigator to the Home screen with the initialRouteName prop:
const MyStack = () => {
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Tabs" component={MyTabs} />
<Stack.Screen name="Home" component={HomeStack} />
</Stack.Navigator>
);
}
Then, in the HomeStack component, you can navigate to the Tabs screen within the Home component:
const HomeStack = ({ navigation }) => {
return (
<View>
<Text>Home Screen</Text>
<Button
title="Go to Tabs"
onPress={() => navigation.navigate("Tabs")}
/>
</View>
);
};
This way, the Home component will be the initial route and when the user clicks the "Go to Tabs" button, the Tabs screen with the Tab.Navigator will be displayed.
Actually I got this sorted... couldn't have been easier
tabBarItemStyle: { display: "none" }
🤦‍♂️
so my final navigators looked like this with "Home" as one of my BottomTabs
const MyTabs = () =>{
return (
<Tab.Navigator >
<Tab.Screen name="Home" component={HomeStack}
options={{
tabBarItemStyle: { display: "none" },
}}/>
<Tab.Screen name="About" component={AboutStack} />
<Tab.Screen name="Setting" component={SettingStack} />
</Tab.Navigator>
);
}
const MyStack = () => {
return (
<Stack.Navigator initialRouteName="Home"
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Tabs" component={MyTabs} />
</Stack.Navigator>
);
}
Updated Snack
Seems like there is probably a better solution out there but this does the trick for now.

How to use Stack and Tab navigation at same time

Hello I am new to react native and particullary react navigation.
I am stuck on one easy thing, use the tab navigator and the stack navigator at the same time.
I am able to use one at a time but not both at the same time. I didn't fully understood the react navigation doc.
Here is what I am doing :
My navigation file : at first my stack Navigator :
const Stack = createStackNavigator()
export default function MyStack() {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="Profile" component={Profile}/>
<Stack.Screen name="Home" component={Home}/>
<Stack.Screen name="MachinesList" component={MachinesList}/>
<Stack.Screen name="Size" component={Size}/>
<Stack.Screen name="Weight" component={Weight}/>
</Stack.Navigator>
</NavigationContainer>
)
}
and then my tab navigator :
const Tab = createBottomTabNavigator()
export function TabNavigator(){
return(
<Tab.Navigator>
<Tab.Screen name='Profile' component={Profile}/>
<Tab.Screen name='Home' component={Home}/>
<Tab.Screen name='MachinesList' component={MachinesList}/>
</Tab.Navigator>
)
}
And here is how I try to put my navigation in my App.js :
return (
<Provider store={store}>
<MyStack />
</Provider>
You need to define which screens are located in which tabs. Currently, you have three tabs that hold screens that are all located on the same stack.
Usually, this works as follows.
Define a tab navigator with n tabs
Define n stacks
Assign each stack to the corresponding tab
Assign the screens to their stacks
In your case, this looks as follows.
const Tab = createBottomTabNavigator()
export function TabNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name='Profile' component={ProfileStack}/>
<Tab.Screen name='Home' component={HomeStack}/>
<Tab.Screen name='MachinesList' component={MachineListStack}/>
</Tab.Navigator>
)
}
The HomeStack then looks as follows.
const Stack = createStackNavigator()
const HomeStack = () => {
return (
<Stack.Navigator initialRoutName="HomeScreen">
<Stack.Screen name="HomeScreen" component={HomeScreen} />
// all other screens located inside the stack of the tab Home
</Stack.Navigator>
)
}
Do the same for all other stacks. Now, you have three tabs with three stacks. You can nest as many screens inside each stack as you like.
In your main application, you then initialize the TabNavigator.
export default function App() {
return (
<NavigationContainer>
<TabNavigator />
</NavigationContainer>
);
}
You need to add your TabNavigator as a Stack.Screen within Stack.Navigator.
const Stack = createStackNavigator()
export default function MyStack() {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="Profile" component={TabNavigator}/>
<Stack.Screen name="Home" component={Home}/>
<Stack.Screen name="MachinesList" component={MachinesList}/>
<Stack.Screen name="Size" component={Size}/>
<Stack.Screen name="Weight" component={Weight}/>
</Stack.Navigator>
</NavigationContainer>
)
}
You can see now that Profile Stack.Screen are using TabNavigator.

Stack navigator header disappear and can't use navigation.navigate(

I have this navigation structure:
const TabNavigator = () => {
return (
<Tab.Navigator>
<Tab.Screen name='dashboard' component={Dashboard} />
<Tab.Screen name='info' component={Info} />
</Tab.Navigator>
);
};
const App = () => {
return (
<SafeAreaProvider>
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name='main' component={TabNavigator} />
<Stack.Screen name='market' component={Market} />
<Stack.Screen name='cart' component={Cart} />
<Stack.Screen name='ongoingdelivery' component={OngoingDelivery} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
</SafeAreaProvider>
);
};
the first screen shown is "Dashboard" whose live inside the "TabNavigator". After that, inside "Market" component, on a button, I use props.navigation.navigate('market') and I successfully navigate to market, inside Market component, I navigate to "Cart" the same way. So when I am on "Cart" screen, I try to use props.navigation.navigate('ongoingdelivery') and nothing happens. Not even an error is thrown. But if I instead of "ongoingdelivery" I navigate back to market, it works. why?

React Native show header and back button on drawer navigation screen

I just add drawer navigation and works fine, but in options, there is not a headerShown as Stack has.
I created a few screen examples, and use tapbar, stack and drawer in the same file.+
I searched on some YouTubes and there is not a specific explanation
Thank you.
You can see my current app: GIF HERE
HomeStack
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
Drawer
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={MainScreen} />
<Drawer.Screen
name="Leaderboards"
component={Leaderboards}
options={{
drawerIcon: (config) => <AntDesign size={23} name="user" />,
}}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
````
Drawer screen has no header option. You can either make your own header component for your Leaderboards screen or nest a stack navigator that contains the Leaderboards screen within your drawer screen and customize the header through the options properties.

Trying to create a React Navigation Drawer with custom content

I am trying to create a React Navigation drawer with custom content (I want to put profile information, probably not any links). I am having a ton of trouble doing so.
Here's my basic stack/drawer:
const Drawer = createDrawerNavigator();
function DrawerNav() {
return (
<ScrollView>
<DrawerItems {...props} />
<Text>Test Content</Text>
</ScrollView>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={Login} options={{
headerShown: false
}} />
<Stack.Screen name="Detail" component={Detail} />
<Stack.Screen name="Chat" component={Chat} />
<Stack.Screen name="Leagues" component={Leagues} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Home" component={Home} options={{
headerRight: (navigation) => (
<TouchableOpacity onPress={(navigation) => navigation.dispatch(DrawerActions.toggleDrawer())}>
<EvilIcons name="navicon" size={50} color="black" />
</TouchableOpacity>
),
headerLeft: () => (
null
),
}} />
<Stack.Screen name="CommForm" component={CommForm} />
</Stack.Navigator>
</NavigationContainer>
);
}
All I want, literally all I want, is a sidebar that I can toggle by pressing the <TouchableOpacity> button above with custom content inside of it.
I am able to do this with React Native Side Menu, but it seems like if I am using React Navigation, I should learn how to do it with this library, however it seems very difficult to do what I am trying to do.
How do I create a sidebar with custom content with React Navigation? I primarily want to use Stack navigation.
I would do something like this:
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItem label="..." />
// ...
</DrawerContentScrollView>
);
}
function StackNavigator({navigation}) {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{
headerRight: () => (
<Button title="press" onPress={() => navigation.toggleDrawer()} />
),
}}
/>
// Your other screens...
</Stack.Navigator>
);
}
function DrawerNavigator({navigation, route}) {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="Stack" component={StackNavigator} />
</Drawer.Navigator>
);
}
const App = () => {
return (
<NavigationContainer>
<DrawerNavigator />
</NavigationContainer>
);
};
So you can set the drawer navigation to be your main navigator and your stack navigation to be a screen of the drawer navigation. This way you can toggle the drawer without first navigating to it.
For creating custom drawer content you can pass a component to the drawerContent on the drawer navigator.
If you're going to use DrawerContentScrollView and/or DrawerItem like I've done in this example, be sure to import it from '#react-navigation/drawer'; .
Look at the documentation for more information https://reactnavigation.org/docs/drawer-navigator/#providing-a-custom-drawercontent.

Categories

Resources