How to I hide screens using DrawerNavigator in React Native - 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.

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

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

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;

how to turn off navigation in tabnavigator

I want user to set preferences first and then be able to navigate the app.
I have nested stack inside tabnvaigator is there any way to disable other tabs and prompt user to set preferences first
tabnavigator code
const tab=createBottomTabNavigator()
return (
<tab.Navigator
initialRouteName="profile"
tabBarOptions={{
activeTintColor: '#0000A0',
inactiveTintColor: 'gray',
keyboardHidesTabBar:true
}}>
<tab.Screen name="personal" component={personalNav}
options={{
tabBarIcon:({color,size})=>{ return <Icon name='person-outline' size={size} color={color} />;}
}}/>
<tab.Screen name="general" component={genRecomNav}
options={{
tabBarIcon:({color,size})=>{ return <Icon name='explore' size={size} color={color} />;}
}}/>
<tab.Screen name="profile" component={profileNav}
options={{
tabBarIcon:({color,size})=>{ return <Icon name='fingerprint' size={size} color={color} />;}
}}/>
</tab.Navigator>
)
stacknavigator code
const profileNav = createStackNavigator();
return (
<profileNav.Navigator headerMode="none" screenOptions={
{
gestureEnabled:false,
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
transitionSpec:{
open:TransitionSpecs.FadeInFromBottomAndroidSpec ,
close:TransitionSpecs.TransitionIOSSpec,
}
}} >
<profileNav.Screen name="profileMain" component={profileMain}/>
<profileNav.Screen name="preference" component={preference}/>
<profileNav.Screen name="preferenceApp" component={preferenceApp}/>
<profileNav.Screen name="preferenceTopic" component={preferenceTopic}/>
</profileNav.Navigator>
)