Turning off the drawer header in a specific screen in bottom tab navigation in drawer navigation in react native - 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

Related

How to I hide screens using DrawerNavigator in React Native

I have created a Drawer Navigator with some screens that I want the user to be able to see and access, however, I also want to be able to navigate to a screen in which the user can only access if they press a button to go to. So that screen should not be accessible through the drawer screen. The problem is that I have no idea how to do that. I have searched everywhere and still didn't fidn a way to do it.
AppStack.js:
const Drawer = createDrawerNavigator();
const AppStack = () => {
return (
<Drawer.Navigator
drawerContent={props => <CustomDrawer {...props}/>}
screenOptions={{headerShown: false,drawerActiveBackgroundColor: '#000c1a', drawerActiveTintColor: 'white', drawerInactiveTintColor: 'white', drawerLabelStyle: {marginLeft: -25, fontSize: 17}}}
>
<Drawer.Screen name="Home" component={HomeScreen} options={{
drawerIcon: ({color}) => (
<Ionicons name="home-outline" size={24} color={color} />
)
}}/>
<Drawer.Screen name="Inventory" component={ListingScreen} options={{
drawerIcon: ({color}) => (
<Ionicons name="car-sport-outline" size={24} color={color} />
)
}}/>
<Drawer.Screen name="Iventory" component={ListingScreen} options={{
drawerIcon: ({color}) => (
<Ionicons name="car-sport-outline" size={24} color={color} />
)
}}/>
<Drawer.Screen name="Inventy" component={ListingScreen} options={{
drawerIcon: ({color}) => (
<Ionicons name="car-sport-outline" size={24} color={color} />
)
}}/>
<Drawer.Screen name="Invent" component={ListingScreen} options={{
drawerIcon: ({color}) => (
<Ionicons name="car-sport-outline" size={24} color={color} />
)
}}/>
</Drawer.Navigator>
)
}
export default AppStack
App.js
export default function App() {
const Stack = createNativeStackNavigator()
return (
<View style={styles.container}>
<NavigationContainer theme={MyTheme}>
<AppStack/>
</NavigationContainer>
</View>
);
}
Is there any way I could do this?
To make it easier to understand, I have a list of cars that whenever a user press on the picture of the car, it will go to a vehicle details screen with the info of the car the user clicked.
I'd really appreciate any help.

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

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>

Dynamic initialRouteName in BottomTabNavigator - React Navigation v5

I want to set a dynamic initialRouteName on my TabNavigator (not even sure if this is the right place to do it), let me explain more clearly.
I have a BottomTabNavigator with 4 items : Home (HomeStack), Explorer (ExplorerStack), subscriptions (SubscribeStack) & contact (contactStack). When the app load, with the token I was redirecting the user to my MainNavigator (so my BottomTabNavigator) with the initialRouteName Home.
<Stack.Navigator headerMode="none">
{!token ? (
<Stack.Screen
isSignout={isSignout}
name="AuthStack"
component={AuthNavigator}
/>
) : (
<Stack.Screen name="HomeStack" component={MainNavigator} />
)}
</Stack.Navigator>
What I want to do now is : when the user is not null and have no subscriptions I want to redirect him directly to the Explorer Tab and not the Home Tab.
// MainNavigator.js
const MainNavigator = (props) => {
const [loading, setLoading] = useState(true);
const [subs, setSubs] = useState([]);
const [fetchData, {data: meData}] = useLazyQuery(USER_ME_QUERY);
useEffect(() => {
fetchData();
if (meData) {
setSubs(meData.me.subscribes);
setLoading(false);
}
}, [meData]);
if (loading) {
return <Loading />;
}
return (
<Tab.Navigator
initialRouteName={subs.length > 0 ? 'Home' : 'Explorer' }
tabBarOptions={{
shadowColor: 'transparent',
showLabel: false,
style: {
backgroundColor: dark ? theme.color.secondary : theme.color.white,
elevation: 0, // for Android
borderTopColor: dark ? '#46505C' : theme.color.lightBorder,
},
}}>
<Tab.Screen
name="Home"
component={HomeStack}
options={{
tabBarIcon: ({focused}) =>
focused ? (
<Icon size={22} name="home" color={theme.color.primary} />
) : (
<Icon size={22} name="home" color={theme.color.lightGrey} />
),
}}
/>
<Tab.Screen
name="Explorer"
component={ExplorerStack}
options={{
tabBarIcon: ({focused}) =>
focused ? (
<Icon size={22} name="columns" color={theme.color.primary} />
) : (
<Icon size={22} name="columns" color={theme.color.lightGrey} />
),
}}
/>
<Tab.Screen
name="Subscribe"
component={SubscribeStack}
options={{
tabBarIcon: ({focused}) =>
focused ? (
<Icon size={22} name="sliders" color={theme.color.primary} />
) : (
<Icon size={22} name="sliders" color={theme.color.lightGrey} />
),
}}
/>
<Tab.Screen
name="Contact"
component={ContactStack}
options={{
tabBarIcon: ({focused}) =>
focused ? (
<Icon size={22} name="mail" color={theme.color.primary} />
) : (
<Icon size={22} name="mail" color={theme.color.lightGrey} />
),
}}
/>
</Tab.Navigator>
);
};
export default MainNavigator;
Is there a simple way to achieve this ? Any help would be appreciated x
If you need more infos, feel free to ask :)
Thanks in advance x

Always show BottomTabNavigation

How can I show BottomTabNavigation even on stacked screen? I have tried this for a few hours but really don't get it to work as expected.
So the thing I want to happen is, if I navigate to say for example the Title Screen, I still want to show the BottomTabNavigation. Any suggestions?
I can of course create a new navigation, but then it is sliding in from the side.
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
const HomeTabNavigator = () => {
return (
<Tab.Navigator
tabBarOptions={{
labelStyle: {textTransform: 'uppercase'},
style: {
backgroundColor: '#111111', //Färger på footerbar
borderTopColor: 'transparent',
borderBottomColor: 'transparent',
},
}}>
<Tab.Screen
name={'Concerts'}
component={ConcertsScreen}
options={{
tabBarIcon: ({tintColor}) => (
<Image
source={require('../../assets/icons/concerts.png')}
size={25}
/>
),
}}
/>
<Tab.Screen
name={'Docs'}
component={DocumentiesScreen}
options={{
tabBarIcon: ({tintColor}) => (
<Image source={require('../../assets/icons/docs.png')} size={25} />
),
}}
/>
<Tab.Screen
name={'Profile'}
component={ProfileScreen}
options={{
tabBarIcon: ({tintColor}) => (
<Image source={require('../../assets/icons/user.png')} size={25} />
),
}}
/>
</Tab.Navigator>
);
};
const Router = () => {
const {token, setToken} = useContext(TokenContext);
const {userFav, addFav, getFav} = useContext(UserContext);
const [isLoading, setLoading] = useState(true);
useEffect(() => {
setLoading(false);
setTimeout(() => {}, 1000);
}, []);
return (
<NavigationContainer>
{token ? (
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerTransparent: true,
noBorder: true,
}}
headerMode="float">
<Stack.Screen name={' '} component={HomeTabNavigator} />
<Stack.Screen name={'Concerts'} component={ConcertsScreen} />
<Stack.Screen name={'User Profile'} component={ProfileScreen} />
<Stack.Screen
name={'FavouritesScreen'}
component={FavouritesScreen}
/>
<Stack.Screen name={'Docs'} component={DocumentiesScreen} />
<Stack.Screen name={'AccountScreen'} component={AccountScreen} />
<Stack.Screen name={'Home of'} component={SearchScreen} />
<Stack.Screen name={'Artist'} component={ArtistScreen} />
<Stack.Screen name={'Title'} component={Videos} />
<Stack.Screen name={'PlayVideo'} component={PlayVideo} />
</Stack.Navigator>
) : (
<LoginScreen />
)}
</NavigationContainer>
);
};
You need to nest all your stack screens inside a tab screen.
The BottomTabNavigator disappear because you leave your Tab.Navigator component.
I hope this helps. If you want to navigate between screens that are related to a specific tab button, and have that tab button remain active while moving between these screens, you should set up a StackNavigation within that tab's component. By doing so, the tab button will remain active while navigating within its related screens.
On the other hand, if you want the TabNavigation to be visible throughout the whole application but some screens should not be displayed as tabs, you can add all screens inside the TabNavigation and specify in the options for those screens not to be displayed as tab buttons. That way, while in the screen without a tab button, the tabs will still be visible but none will be active. For example, you can do this for a screen called 'Title':
<Tab.Screen
name={'Title'}
component={Videos}
options={{
tabBarIcon: ({tintColor}) => (
<Image source={require('../../assets/icons/user.png')} size={25} />
),
tabBarButton: () => null <---- *this causes it to have no button*
}}
/>
I hope this helps!

Reversing tab navigator direction to support RTL react navigation

I have been trying to change the tab direction to RTL instead of LTR. Unfortunately, I cannot find out how it works. I used flextDirection in tabBarStyle or style props as "row" or "row-reverse", but when I did so, the whole tab was removed. It only appeared when using column or column-reverse showing at the top or bottom of the screen. Here is my code:
const Tab = createMaterialBottomTabNavigator();
<Tab.Navigator
activeColor={theme.colors.text}
inactiveColor={theme.colors.textAlt}
barStyle={{
backgroundColor: theme.colors.background,
flexDirection: "row-reverse", //In this case an empty tab bar only appears with no screens. Screens only appear when it changes to column
}}
shifting={true}
screenOptions={defaultNavOptions}>
<Tab.Screen
name={userConfig.appTexts.homeScreenName}
component={AppNavigator}
options={{
tabBarIcon: ({ color, size }) => {
return <Ionicons name="ios-home" color={color} size={22} />;
},
}}
initialParams={{ theme, taxonomy }}
/>
<Tab.Screen
name={userConfig.appTexts.settingScreenName}
component={SettingNavigator}
options={{
tabBarIcon: ({ color, size }) => {
return <Ionicons name="ios-settings" color={color} size={22} />;
},
}}
initialParams={{ theme }}
/>
<Tab.Screen
name={userConfig.appTexts.savedScreenName}
component={PostNavigator}
options={{
tabBarIcon: ({ color, size }) => {
return <Ionicons name="md-bookmark" color={color} size={22} />;
},
}}
initialParams={{ saved: true, theme }}
/>
</Tab.Navigator>
I guess you can change style in the tabBarOptions :
<Tab.Navigator
tabBarOptions={{
style: {transform: [{scaleX: -1}]},
}}> {Your}
</Tab.Navigator>
Simply reverse your Tab screens order inside Tab Navigator. So move the last screen to be the first and...