React Navigation 5 Hide Drawer Item
Solution 1
Solved the issue with the following
import React from 'react';
import { SafeAreaView, View, Text, StyleSheet, Image, Linking } from 'react-native';
import { EvilIcons, AntDesign } from '@expo/vector-icons';
import { useDispatch } from 'react-redux';
import { createDrawerNavigator, DrawerContentScrollView, DrawerItemList, DrawerItem } from '@react-navigation/drawer';
import MainTabNavigator from './MainTabNavigator';
import FAQStackNavigator from './FAQStackNavigator';
import { TouchableOpacity } from 'react-native-gesture-handler';
import * as authActions from '../store/actions/auth';
import { moderateScale } from '../utils/fontScale';
const MainDrawerNavigator = createDrawerNavigator();
const DrawerNavigator = () => {
const dispatch = useDispatch();
return (
<MainDrawerNavigator.Navigator
drawerContent={props => customDrawerContent(props, dispatch)}
drawerStyle={drawerStyle}
>
<MainDrawerNavigator.Screen
name="DrawerNav"
component={MainTabNavigator}
options={{
drawerLabel: () => null,
title: null,
drawerIcon: () => null
}}
/>
<MainDrawerNavigator.Screen
name="FAQNav"
component={FAQStackNavigator}
options={
{
drawerLabel: "FAQ",
drawerIcon: ({tintColor}) => <EvilIcons name={'question'} size={30} color={tintColor} />
}
}
/>
</MainDrawerNavigator.Navigator>
)
}
const customDrawerContent = (props, dispatch) => {
return (
<View style={{flex: 1}}>
<View style={{height: '90%'}}>
<DrawerContentScrollView {...props}>
<View style={styles.logoContainer}>
<Image
style={styles.image}
fadeDuration={0}
resizeMode={'contain'}
source={require('...')}
/>
</View>
<TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('...')}}>
<AntDesign style={styles.iconStyle} name={'shoppingcart'} size={25} color={'black'} />
<Text style={styles.drawerText}>Shop</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('...')}}>
<AntDesign style={styles.iconStyle} name={'contacts'} size={25} color={'black'} />
<Text style={styles.drawerText}>Contact Us</Text>
</TouchableOpacity>
{/* Tried just disabling using DrawerItemList but wasn't working so made
complete custom drawer component and navigate properly using props.navigation.navigate */}
{/* <DrawerItemList
{...props}
/> */}
<TouchableOpacity
style={styles.contactUsContainer}
onPress={() => { console.log(props.navigation.navigate('FAQNav'))}}
>
<EvilIcons name={'question'} size={30} color={'black'} />
<Text style={styles.drawerText}>FAQ</Text>
</TouchableOpacity>
</DrawerContentScrollView>
</View>
<TouchableOpacity
style={styles.logoutContainer}
onPress={() => {
dispatch(authActions.logout());
}}>
<Text style={styles.logoutText}>SIGN OUT</Text>
</TouchableOpacity>
</View>
)
}
const drawerStyle = {
activeTintColor: 'black',
inactiveTintColor: 'black',
labelStyle: {
fontFamily: 'montserrat',
marginVertical: 16,
marginHorizontal: 0,
},
iconContainerStyle: {
justifyContent: 'center',
alignItems: 'center',
},
itemStyle: {
}
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
paddingTop: Platform.OS === 'android' ? 25 : 0
},
container: {
flex: 1,
},
logoContainer: {
width: '100%',
height: moderateScale(50),
alignItems: 'center',
justifyContent: 'center',
marginBottom: 5,
padding: 5,
},
image: {
resizeMode: 'contain',
width: '80%',
height: '100%',
},
contactUsContainer: {
flexDirection: 'row',
width: '100%',
height: 50,
alignItems: 'center',
paddingLeft: 15
},
logoutContainer: {
flexDirection: 'row',
width: '100%',
height: 50,
alignItems: 'flex-end',
justifyContent: 'center',
},
drawerText: {
fontFamily: 'montserrat',
marginLeft: 16,
},
logoutText: {
fontFamily: 'montserrat',
color: '#b23b3b'
}
});
export default DrawerNavigator;
Solution 2
Best solution will be filter the props before pass it to DrawerItemList . This will only work react navigation 5
//custom drawer content
export default props => {
const { state, ...rest } = props;
const newState = { ...state} //copy from state before applying any filter. do not change original state
newState.routes = newState.routes.filter(item => item.name !== 'Login') //replace "Login' with your route name
return (
<DrawerContentScrollView {...props}>
<DrawerItemList state={newState} {...rest} />
</DrawerContentScrollView>
)
}
Solution 3
Having looked through the React Navigation source code, I think the best option would be to add a drawerItemStyle option to the drawer screen that you want to hide. Just set the height to 0.
E.g.
<Drawer.Screen
name="Home"
component={MainStackScreen}
options={{
drawerItemStyle: { height: 0 }
}}
/>
It seems to work perfectly.
I'm using React Navigation 6 but this will probably apply to v5 also.
Solution 4
This works Perfectly
<Drawer.Screen name="Home" component={MainStackScreen}
options={{
drawerItemStyle: { display: 'none' }
}}
/>
Solution 5
For me you would better creating a nested navigator with stack and drawer screens as documented in https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside instead of hiding drawer item.
Related videos on Youtube
SKeney
Updated on July 09, 2022Comments
-
SKeney almost 2 years
I am trying to hide the ability to press one of my routes in the drawer navigator as it is another navigator and the default location in the app. I want the drawer to simply be used for navigating to extraneous routes that don't fit well into user flow elsewhere. Before React Navigation 5 I was able to achieve this by simply setting
drawerLabel: () => null
. However now with the changes I cannot figure out how to hide this in the same manner.Below is my current navigator code:
const DrawerNavigator = () => { const dispatch = useDispatch(); return ( <MainDrawerNavigator.Navigator drawerContent={props => customDrawerContent(props, dispatch)} drawerStyle={drawerStyle} > <MainDrawerNavigator.Screen name="DrawerNav" component={MainTabNavigator} options={{ drawerLabel: () => null, title: null, drawerIcon: () => null }} /> <MainDrawerNavigator.Screen name="FAQNav" component={FAQStackNavigator} options={ { drawerLabel: "FAQ", drawerIcon: ({tintColor}) => <EvilIcons name={'question'} size={30} color={tintColor} /> } } /> </MainDrawerNavigator.Navigator> ) } const customDrawerContent = (props, dispatch) => { console.log(props.descriptors) return ( <View style={{flex: 1}}> <View style={{height: '90%'}}> <DrawerContentScrollView {...props}> <View style={styles.logoContainer}> <Image style={styles.image} fadeDuration={0} resizeMode={'contain'} source={require('../assets/images/spikeball-logo-horizontal.png')} /> </View> <TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('https://spikeball.com/')}}> <AntDesign style={styles.iconStyle} name={'shoppingcart'} size={25} color={'black'} /> <Text style={styles.drawerText}>Shop</Text> </TouchableOpacity> <TouchableOpacity style={styles.contactUsContainer} onPress={() => { Linking.openURL('https://support.spikeball.com/')}}> <AntDesign style={styles.iconStyle} name={'contacts'} size={25} color={'black'} /> <Text style={styles.drawerText}>Contact Us</Text> </TouchableOpacity> <DrawerItemList {...props} /> </DrawerContentScrollView> </View> <TouchableOpacity style={styles.logoutContainer} onPress={() => { dispatch(authActions.logout()); }}> <Text style={styles.logoutText}>SIGN OUT</Text> </TouchableOpacity> </View> ) }
Link to image showing the undesired output. Basically I want the blue focus and entire nav item hidden from the naw bar specifically. UNDESIRED Output
-
Matheus almost 4 yearsThis is also a not good solution, I've tried this. when doing that all you do is replace a bunch of screens you want to hide in drawer for "one" screen which is the stack navigator, for instance. Maybe you could provide a better example other than linking the docs, which are kida poor. Thanks
-
SKeney almost 4 years@Matheus In my application they are not clickable at all. There is no clickable space. If I inspect the actual elements in the drawer they are not viewable or clickable.
-
harshit raghav almost 4 yearsThe drawer item is hidden but I can still some space at that position. Do you know how that can be removed?
-
SKeney almost 4 years@harshitraghav I accomplished it by creating my own drawer content above
customDrawerContent
. If you noticeDrawerItemList
is commented out and then I handle navigation myself with my own item components. -
Matheus almost 4 yearsI have to apologize. I didn't check the part where you draw every item, it really worked. Change some letter in your answer so I can change my vote. Thanks for this answer.
-
SKeney almost 4 years@Matheus No worries! Glad it helped!
-
MayankBudhiraja over 3 yearsHow to hide multiple drawer items?
-
Lenin Sheikh over 3 yearshey @MayankBudhiraja update the Filter like this: newState.routes = newState.routes.filter(item => !['RouteOne', 'Login', 'Signup' ].includes(item.name));
-
targhs over 3 yearsNot working in my case. Did exactly the same thing. Asking another question.
-
Gowtham over 3 yearsThis is working. But the first item in the drawer had a blue background. Had to pass activeBackgroundColor={'transparent'} in DrawerItemList. Thanks.
-
ffritz over 3 yearsWorking as expected!
-
rafaelmorais over 3 yearsTo add to what @Matheus wrote, when I tried this way I was seeing some weird flickering on iOS and when tested it with the drawer as the top navigator its was pretty smooth.
-
Nisharg Shah over 3 yearsworking but sometimes it is not navigate to another screen
-
Raphael Pinel over 3 yearsSame as @Nisharg Shah, It does not navigate to the 2nd screen on the list.
-
Raphael Pinel over 3 yearsFor it to work, you need to replace <DrawerItemList> with the items you want to have in the list:
<DrawerItem label={'yourNavItem'} onPress={() => props.navigation.navigate('yourNavItem')} labelStyle={styles.mainItem} />
-
Admin over 3 yearsSomeone please help me I have same problem But I do not know what should I modify In code. Check this link = stackoverflow.com/questions/65679208/…
-
Bryson Kruk over 2 yearsThis led me to try using display: "none" instead of height: 0 and it worked perfectly! It also removed the built-in padding/margin
-
Nobady over 2 yearssimple and effective ;-)
-
Md. Sultanul Arefin over 2 yearsyes @BrysonKruk answer worked for me, V6 drawerItemStyle: {display: (current_Role===1)?"flex":"none",}
-
nicholascm over 2 years@BrysonKruk I think yours should be the accepted answer :) Very simple and works well.
-
Abid Ali about 2 yearsthis hides the drawer item but we see an extra space between the items where this hidden item was.
-
Lucas Garcez about 2 yearsthe code works on v6 too!