ReactNative: Using Drawer.Navigator inside TabNavigator throws "navigation.openDrawer is not a function" - react-native

What I want to achive:
Tap on an icon in bottomTabNavigator to open DrawerNavigator.
What I get:
An error stating: "TypeError: navigation.openDrawer is not a function. (In 'navigation.openDrawer()', 'navigation.openDrawer' is undefined)"
My Code:
<NavigationContainer>
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor: '#e91e63',
style: {},
labelStyle: {margin:0},
}}
>
<Tab.Screen
name="Home"
component={HomeStack}
options={{
tabBarLabel: 'News',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="newspaper" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Categories"
component={CategorieStack}
options={{
tabBarLabel: 'Kategorien',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="format-list-bulleted-square" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Menu"
component={DrawerStack}
options={{
tabBarLabel: 'Menu',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="menu" color={color} size={size} />
),
}}
listeners={({ navigation }) => ({
tabPress: e => {
e.preventDefault();
navigation.openDrawer();
}
})}
/>
</Tab.Navigator>
</NavigationContainer>
and
const Drawer = createDrawerNavigator();
function DrawerStack() {
return (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Categories" component={Categories} />
</Drawer.Navigator>
);
}
Already read:
https://github.com/react-navigation/hooks/issues/36
Opening the Drawer navigator from the bottom tab
And many more. Just can't seem to get it to work. I think I do miss a really important point in this. Is anyone able to point me into the right direction?

In my case, my bottomTabNavigator is a child of my drawerNavigator( not sure if this is required for it to work tho)
so using this bit works:
listeners={({ navigation }) => ({
tabPress: e => {
e.preventDefault();
navigation.openDrawer();
}
})}
Inside Drawer Navigator:
<Drawer.Navigator
initialRouteName="MyRoute"
drawerStyle={styles.drawerStyle}
lazy
>
{/*Bottom Tab Navigator*/}
<Drawer.Screen
name="MyRoute"
component={MyBottomTabs}
options={{
drawerIcon: ({ focused, size }) => (
<Ionicons
name={focused?"md-home": "md-home-outline"}
size={size}
color={focused ? COLORS.primary : '#ccc'} />
)
}}
/>
<Drawer.Screen
name="Profile"
component={UserProfile}
options={{
drawerIcon: ({ focused, size }) => (
<Ionicons
name={focused?"md-person-sharp": "md-person-outline"}
size={size}
color={focused ? COLORS.primary : '#ccc'} />
)
}}
/>
<Drawer.Screen
name="Elect"
component={WebViewElect}
options={{
drawerIcon: ({ focused, size }) => (
<Entypo
name="new"
size={size}
color={COLORS.danger} />
),
}}
/>
</Drawer.Navigator>
Inside MyBottomTabs:
<Tabs.Navigator initialRouteName="Dashboard" >
{/*Bottom Tab Screens */}
<Tabs.Screen name="Dashboard" component={DashboardStack}/>
<Tabs.Screen name="Refer A Friend" component={WebViewRefer}
options={{
tabBarButton: () => null,
tabBarVisible: false
}}
listeners={({ navigation }) => ({
tabPress: e => {
console.log('Button Pressed')
e.preventDefault();
return navigation.openDrawer();
}
})}
/>
</Tabs.Navigator>

Related

Turning off the drawer header in a specific screen in bottom tab navigation in drawer navigation in react native

I have a very big problem I am using two navigations in one app the first one is the drawer navigator this is how I use the drawer navigator:
<Drawer.Navigator
screenOptions={{
drawerStyle: {
backgroundColor: 'white',
},
}}
drawerContent={props => <CustomSidebarMenu {...props} />}
drawerContentOptions={{
activeTintColor: '#e91e63',
activeBackgroundColor: 'red',
itemStyle: {marginVertical: 20},
}}>
<Drawer.Screen
options={{
headerShown: true,
headerTitle: () => (
<Image
style={{height: 150, width: 100, resizeMode: 'contain'}}
source={require('../assets/images/referans2.png')}
/>
), // Title to appear in the header
headerRight: ({navigation, scene}) => (
// Custom component to appear on the right side of the header
<View style={{flexDirection: 'row'}}>
<Pressable>
<Ionicons
name="notifications-outline"
size={30}
color={'black'}
/>
</Pressable>
<Pressable style={{marginHorizontal: 10}}>
<Ionicons
name="chatbubbles-outline"
size={30}
color={'black'}
/>
</Pressable>
</View>
),
}}
name="Ana Sayfa"
component={Main}
/>
<Drawer.Screen
options={{headerShown: true}}
name="Şiparişlerim"
component={MyOrders}
/>
<Drawer.Screen name="Adreslerim" component={AddressesScreen} />
<Drawer.Screen name="Üyelik Bilgilerim" component={AccountInfoScreen} />
</Drawer.Navigator>
[
and this gives me the following output:](https://i.stack.imgur.com/73o8f.png)
In the main function you see here, the bottomtabnavigator, which I use in the whole app, returns.:
const Main = () => {
return (
<Tab.Navigator screenOptions={screenOptions}>
<Tab.Screen
component={HomeStack}
name="Ana Sayfa"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="home-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={CategoriesStack}
name="Kategoriler"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="grid-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={CartStack}
name="Sepet"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="cart-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={DiscoverStack}
name="Keşfet"
options={{
tabBarIcon: ({focused, color}) => (
<Ionicons name="compass-outline" size={28} color={color} />
),
}}
/>
<Tab.Screen
component={ProfileStack}
name="Profilim"
options={{
headerShown: true,
tabBarIcon: ({focused, color}) => (
<Ionicons name="person-circle-outline" size={28} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
What I want is this; Turning off the header of the drawer in the profile stack in the bottom tab navigator, but I can't do it
but it still didn't close the header of the drawer navigation. Even if I set the headershown of the drawer to false, the header on all screens closes, I'm just not on the screen I want
As far as I understand, there are 3 nested navigator.
Drawer
|---------> BottomTab
| |---------> ProfileStack
|... |...
If you want to hide or show only specific screen you can use navigation.setOptions()
For example,we have a Profile screen in ProfileStack and get navigation with screen props or useNavigation()
If you want to hide ProfileStack header in Profile:
React.useLayoutEffect(() => {
navigation.setOptions({ headerShown:false })
})
If you want to hide BottomTab header in Profile:
React.useLayoutEffect(() => {
navigation.getParent().setOptions({ headerShown:false })
})
If you want to hide Drawer header in Profile:
React.useLayoutEffect(() => {
navigation.getParent().getParent().setOptions({ headerShown:false })
})
You can use setOptions with headerShown:true when the drawer screenOptions headerShown:false
react-navigation getParent() and setOptions() docs

React Native Tab Navigator

I am totally new to React Native and I am currently trying show BottomTabNavigator on child/details page, for example:
I have a page called Training and I have another page called TrainingDetails.
I wanna show BottomTabNavigator on TrainingDetails.
On truth, I wanna show BottomTabNavigator in all pages, main pages and detail pages.
Here is my Main.js
Thanks so much!
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator tabBarOptions={{ activeTintColor: theme.colors.primary, inactiveTintColor: theme.colors.neutral_100, style: {backgroundColor: theme.colors.active} }}>
<Tab.Screen
options={{
title: "Trabalhar",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"headset"} size={size} color={color} />
),
}}
name="Home"
component={HomeScreen}
/>
<Tab.Screen
options={{
title: "Estudar",
tabBarIcon: ({ focused, color, size }) => (
<SimpleLineIcon name={"graduation"} size={size} color={color} />
),
}}
name="Study"
component={Training}
/>
<Tab.Screen
options={{
title: "Notificações",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"bell-outline"} size={size} color={color} />
),
}}
name="Notification"
component={HomeScreen}
/>
<Tab.Screen
options={{
title: "Resultados",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"trending-up"} size={size} color={color} />
),
}}
name="Results"
component={HomeScreen}
/>
<Tab.Screen
options={{
title: "Carteira",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"wallet-outline"} size={size} color={color} />
),
}}
name="Wallet"
component={HomeScreen}
/>
</Tab.Navigator>
);
};
export default Main;
You can put a stackNavigator inside a tab navigator, so for example if you want a home screen and then another screen called details that doesn't have a tab at the bottom but still has the tabs at the bottom you can replace the home screen with a homeStack that has both a home screen and details screen inside it.
const Stack = createStackNavigator();
function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
);
}
and then replace your home component in the tab navigator with HomeStack component.

why react native navigation keep going to NotFound screen?

I just added new Screen, but the react native navigation keep pointing to NotFound on saving a update. Why?
The index navigation would be something like this from expo init (I don't change anything)
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="Root" component={BottomTabNavigator} />
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
</Stack.Navigator>
And BottomTabNavigator would be something like this
<BottomTab.Navigator
initialRouteName="Require"
tabBarOptions={{
activeTintColor: Colors[colorScheme].tint,
showLabel: false,
}}
>
<BottomTab.Screen
name="Require"
component={RequireNavigator}
options={{
tabBarIcon: ({ color }) => (
<TabBarIcon name="ios-bonfire-outline" color={color} />
),
}}
/>
<BottomTab.Screen
name="Serve"
component={ServeNavigator}
options={{
tabBarIcon: ({ color }) => (
<TabBarIcon name="ios-grid-outline" color={color} />
),
}}
/>
<BottomTab.Screen
name="Publish"
component={PublishNavigator}
options={{
tabBarIcon: ({ color }) => (
<TabBarIcon name="ios-add" color={color} />
),
}}
/>
<BottomTab.Screen
name="Chat"
component={ServeNavigator}
options={{
tabBarIcon: ({ color }) => (
<TabBarIcon name="ios-chatbubbles-outline" color={color} />
),
}}
/>
<BottomTab.Screen
name="About"
component={AboutNavigator}
options={{
tabBarIcon: ({ color }) => (
<TabBarIcon name="ios-information-circle-outline" color={color} />
),
}}
/>
</BottomTab.Navigator>
You can read my full code here: https://github.com/dotku/aladdin

React Native how to programmatically navigate to a stack screen that is on a tab navigator

I have searched tirelessly for an answer to this issue.
I have a Tab Navigator:
const AppNavigator = () => {
return (
<Tab.Navigator initialRouteName="Search">
<Tab.Screen
name="Home"
children={() => <HomeScreen />}
options={{
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Search"
children={() => <SearchContainerNavigator />}
options={{
tabBarIcon: ({ color, size }) => (
<FontAwesome5 name="search" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Feedback"
children={() => <FeedbackScreen />}
options={{
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="email" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
};
And this Stack navigator:
const SearchContainerNavigator = () => (
<Stack.Navigator screenOptions={{ headerShown: false}} initialRouteName="SearchSelect">
<Stack.Screen name="SearchSelect" component={SearchSelectScreen} />
<Stack.Screen name="AircraftSearch" component={AircraftSearchScreen} />
<Stack.Screen name="AircraftResults" component={AircraftResultsScreen} />
<Stack.Screen name="AircraftDetail" component={AircraftDetailScreen} />
<Stack.Screen name="BrandSearch" component={BrandSearchScreen} />
<Stack.Screen name="BrandResults" component={BrandResultsScreen} />
<Stack.Screen name="BrandDetail" component={BrandDetailScreen} />
<Stack.Screen name="Favourites" component={FavouritesScreen} />
</Stack.Navigator>
)
My issue is how do I programmatically navigate from HomeScreen tab to the AircraftDetailsScreen on the Search Tab??
Thanks in advance.
EDIT:
HomeScreen is a class.
handleAircraftSelect = (aircraft_id) => {
this.props.navigation.navigate("Search", {
screen: "AircraftDetail",
params: { id: aircraft_id },
});
};
navigation.navigate('Search', {screen: 'AircraftDetail'});
https://reactnavigation.org/docs/nesting-navigators/#navigating-to-a-screen-in-a-nested-navigator
For react-navigation 6.x you can use this like below:
navigation.jumpTo('Profile', { name: 'Michaś' });

React native i cannot add a new screen without adding it to createMaterialBottomTabNavigator

Hello i want to be able to go to a new page without adding them to <Tab.Screen by another meaning i want to use this.props.navigation.navigate so in order for me to do that i need to add the new screen but how i can add a new screen without adding them to <tab.screen
this is a small sample of my code
const Tab = createMaterialBottomTabNavigator();
const Stack = createStackNavigator();
const App = ({navigation}) => {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="Home" shifting={true}>
<Tab.Screen
name="Feed"
component={mainPage}
options={{
tabBarLabel: 'Home',
tabBarColor: '#29a8ab',
tabBarIcon: ({color}) => (
<Icon name="home" color={color} size={26} />
),
}}
tabBarColor={'#FF0000'}
/>
<Tab.Screen
name="Notifications"
component={cartPage}
options={{
tabBarLabel: 'Shop',
tabBarColor: '#ff8b94',
tabBarIcon: ({color}) => (
<Icon name="cart" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
};
export default createApp;