React Navigation v5 BottomTabNavigator doesn't show when nesting - react-native

BottomTabNavigator doesn't show when code like this:
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
function Bottom() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Setting" component={SettingsScreen} />
</Tab.Navigator>
);
}
function AppRoot() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="HomePage"
screenOptions={{ gestureEnabled: false }}>
//this is bottom tab navigator, it doesn't show.
<Stack.Screen name="Bottom" component={Bottom} />
<Stack.Screen
name="HomePage"
component={HomePage}
/>
<Stack.Screen
name="Page1"
component={Page1}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
AppRegistry.registerComponent(appName, () => AppRoot);
But when I don't use nesting Stack,BottomTabNavigator works fine.
Like this:
function AppRoot() {
return (
<NavigationContainer>
<Bottom />
</NavigationContainer>
);
}
How to use both in one page, normal navigator and bottom tab navigator.

As per your code 'HomePage' is the initial screen and the bottom tab is added on screen named 'Bottom'. Use DrawerNavigator to add sidemenu and you can add bottom tab on one of the screen as show below:
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
function HomeScreen({navigation}) {
return (
<View style={{flex: 1}}>
<View style={{alignSelf:'flex-start'}}>
<Button
onPress={() => navigation.toggleDrawer() }
title="Menu"
/>
</View>
<View style={{alignSelf:'center',justifyContent:'space-around'}}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
</View>
);
}
function Tab1() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Tab1!</Text>
</View>
);
}
function Tab2() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Tab2!</Text>
</View>
);
}
function NotificationsScreen({navigation}) {
return (
<Tab.Navigator>
<Tab.Screen name="Tab1" component={Tab1} />
<Tab.Screen name="Tab2" component={Tab2} />
</Tab.Navigator>
);
}
function SettingsScreen({navigation}) {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Button
onPress={() => navigation.navigate('Home')}
title="Go back home"
/>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home" drawerPosition="left"
drawerType="slide">
<Drawer.Screen
name="Home"
component={HomeScreen}/>
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}

Related

Pass parameter values to drawer Navigator component

Cannot pass parameter to functions or const via Drawer Screen component. Is there any better way to achieve this. the idea is to use single function which change the content accordingly.
function Pagef(param1) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Profile Screen</Text>
<Text>{param1}</Text>
</View>
);
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator useLegacyImplementation initialRouteName="Feed">
<Drawer.Screen
name="Feed"
component={Pagef('Home')}
options={{ drawerLabel: 'Home' }}
/>
<Drawer.Screen
name="Notifications"
component={Pagef('Updates')}
options={{ drawerLabel: 'Updates' }}
/>
<Drawer.Screen
name="Profile"
component={Pagef('Profile')}
options={{ drawerLabel: 'Profile' }}
/>
</Drawer.Navigator>
);
}
Use initialParams to pass route params to component.
<Drawer.Screen name="Feed" component={Pagef} initialParams={{ param1: "Home" }}/>
...
function Pagef({route: {params: {param1}}}) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Profile Screen</Text>
<Text>{param1}</Text>
</View>
);
}

How to inject NativeID to React Navigation material-top-tabs?

I am using #react-navigation/material-top-tabs to display tabs in my application. How can I inject NativeID to tabs to have an access to them with e.g. Selenium?
The only way that I found was using tabBar property, creating custom tabs and adding NativeID to TouchableOpacity. Is there more simple way?
<NavigationContainer>
<Tab.Navigator tabBar={(props) => <MyTabBar {...props} />} >
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
function MyTabBar({ state, descriptors, navigation, position }) {
return (
<View style={{ flexDirection: 'row', paddingTop: 20 }}>
{
state.routes.map((route, index) => {
// ....
return (
<TouchableOpacity nativeID={"tab_"+label} >
<Animated.Text style={{ opacity }}>{label}</Animated.Text>
</TouchableOpacity>
);
})}
</View>
);
}

React Navigation V6 Bottom Tab Not Displaying

I'm following the guide here from React Navigation V6 and my component is not displaying as it is intended to. When I swap out createBottomTabNavigator with createMaterialTopTabNavigator I get my display. Can somebody help me figure out why the output is behaving this way? Photos are attached below the code. Thank you to anybody that can help!
Edit: React-Native-Web sometimes displays things incorrectly. When viewed on a phone it looks correct.
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function FeedScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Feed Screen!</Text>
</View>
);
}
function HomeScreen({ navigation }:any) {
return (
<View >
<Text>Home screen</Text>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile')}
/>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function NotificationsScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Notifications Screen</Text>
</View>
);
}
function ProfileScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Profile Screen</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to tabs"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}
function BasicStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: true }}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
)
}
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Notifications" component={NotificationsScreen} />
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<BasicStack/>
</NavigationContainer>
);
}
Output with createBottomTabNavigator
Output with createMaterialTopTabNavigator

My OnPress does not link to a screen i have made - React Native

I've got 3 screens in a Drawer Navigation and 1 screen in a stack Navigation.
app.js
const Stack = createStackNavigator();
function Navigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Spelare" component={PlayersScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Hem"
drawerPosition="right"
drawerType="slide">
<Drawer.Screen
name="Hem"
component={HomeScreen}
style={styles.drawerItem}
/>
<Drawer.Screen
name="Kontakt"
style={{ color: 'red' }}
component={ContactScreen}
/>
<Drawer.Screen
name="Spelare"
style={{ color: 'red' }}
component={PlayersScreen}
/>
</Drawer.Navigator>
</NavigationContainer>
);
};
function StackNavigator() {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Hem"
drawerPosition="right"
drawerType="slide">
<Drawer.Screen
name="Hem"
component={HomeScreen}
style={styles.drawerItem}
/>
<Drawer.Screen
name="Kontakt"
style={{ color: 'red' }}
component={ContactScreen}
/>
{/* Look down ... */}
<Drawer.Screen
name="Details"
style={{ color: 'red' }}
component={DetailsScreen}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
On the PlayersScreen i've got a FlatList rendering names and when clicking on a name i want it to take the user to Details Screen and load only that person. This all worked when having the DetailsScreen in the Drawer navigator but i don't want that showing in the Drawer menu in the App.
FlatList, Inside playerScreen which is also in the App.js file
<FlatList
data={data}
keyExtractor={item => item.Name}
renderItem={({ item }) => (
<View style={{alignItems: 'center', backgroundColor: '#25D495', borderRadius: 15, fontFamily: 'Roboto, sans-serif', marginBottom: 15, height: 40}}>
<Text
style={styles.listStyle} onPress={() => {navigation.navigate('Details', {itemId: item._id})}}>{item.Name}
</Text>
</View>
)}
/>
I get the following ERROR : The action 'NAVIGATE' was not handled by any Navigator, do you have a screen named Details?
Any help is appreciated.
I'd suggest you replace Spelare screen in your drawer with a StackNavigator like so..
First
Create a stack having both PlayersScreen, and DetailsScreen
const Stack = createStackNavigator();
function StackNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Spelare" component={PlayersScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
);
}
Second
Replace your PlayersScreen in your Main drawer navigator with your created Stack
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Hem"
drawerPosition="right"
drawerType="slide">
<Drawer.Screen
name="Hem"
component={HomeScreen}
style={styles.drawerItem}
/>
<Drawer.Screen
name="Kontakt"
style={{ color: 'red' }}
component={ContactScreen}
/>
{/* Look down ... */}
<Drawer.Screen
name="SpelareStack"
style={{ color: 'red' }}
component={Stack}
/>
</Drawer.Navigator>
</NavigationContainer>
);

Best way to navigate parent router from nested Tab Navigator (Nested Navigation)

I am using react navigation 5.x, I have navigation stack like this.
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Messages" component={Messages} />
</Tab.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Navigator>
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
<Stack.Navigator>
<Stack.Navigator>
<Stack.Screen name="OtherScreen1" component={OtherScreen1} />
<Stack.Screen name="OtherScreen2" component={OtherScreen2} />
<Stack.Navigator>
</Stack.Navigator>
</NavigationContainer>
);
}
Now i need to navigate Feed screen to OtherScreen1. I hope i may have best solution. Thank you,
I drop 2 options. First your answer your question. The long show how you should use react navigation for good practice.
Short answer
navigation.navigate('OtherScreens', { screen: 'OtherScreen1' });
Long answer https://snack.expo.io/#anthowm/navigators
function Feed() {
const navigation = useNavigation();
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Feed!</Text>
<Button onPress={() => {navigation.navigate('OtherScreens', { screen: 'OtherScreen1' });}} title='press'></Button>
</View>
);
}
function Messages() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Messages!</Text>
</View>
);
}
function Profile() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Profile!</Text>
</View>
);
}
function Settings() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
function OtherScreen1() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>OtherScreen1!</Text>
</View>
);
}
function OtherScreen2() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>OtherScreen2!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Messages" component={Messages} />
</Tab.Navigator>
);
}
function MainStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={ProfileStack} />
<Stack.Screen name="OtherScreens" component={OtherScreensStack} />
</Stack.Navigator>
);
}
function ProfileStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
);
}
function OtherScreensStack() {
return (
<Stack.Navigator>
<Stack.Screen name="OtherScreen1" component={OtherScreen1} />
<Stack.Screen name="OtherScreen2" component={OtherScreen2} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MainStack />
</NavigationContainer>
);
}