Reputation: 370
I have a custom navigation drawer and on a particular screen, I don't want it available.
This is my short code.
This navigator is also being included by the switch navigator. I have dig in git-hub and other forums and nothing is currently working. Am I missing something? Is there someone who made it to work?
const UserNavigation = createDrawerNavigator({
ProductListScreen: {screen: ProductListScreen},
ProductHistoryScreen: {
screen: ProductHistoryScreen,
navigationOptions: {
drawerLockMode: 'locked-closed'
}
}
}, {
initialRouteName: 'ProductListScreen',
contentComponent: CustomDrawerContentComponent,
})
export default createAppContainer(UserNavigation)
There is also a working code on expo but I try and and results in double navigators displaying, and also in the screen where I don't want to show the drawer it appears. This is my attempt from referring to expo code
const UserStackNavigation = createStackNavigator({
ProductListScreen: {screen: ProductListScreen},
ProductHistoryScreen: {
screen: ProductHistoryScreen
}
})
const UserNavigation = createDrawerNavigator({
UserStackNavigation: UserStackNavigation
}, {
initialRouteName: 'UserStackNavigation',
contentComponent: CustomDrawerContentComponent,
})
UserStackNavigation.navigationOptions = ({ navigation }) => ({
drawerLockMode: navigation.state.index === 0 ? 'unlocked' : 'locked-closed',
});
export default createAppContainer(UserNavigation)
Upvotes: 14
Views: 16325
Reputation: 807
In my case I do not want the drawer to show up on auth-related pages like login, signup, forgot-password and reset-password. So what I did was have all my auth-related screens on the same stack navigator and then disable the drawer by adding swipeEnabled: false
to the options prop of the Drawer.Screen. See code snippet below:
const Tab = createBottomTabNavigator<TabStackParamsList>();
const HomeStack = createStackNavigator<HomeStackParamsList>();
const AccountStack = createStackNavigator<AccountStackParamsList>();
const AuthStack = createStackNavigator<AuthStackParamsList>();
function HomeStackNavigator() {
return (
<HomeStack.Navigator
initialRouteName="Welcome"
screenOptions={{
headerShown: false,
}}
>
<HomeStack.Screen name="Welcome" component={WelcomeScreen} />
<HomeStack.Screen name="Products" component={ProductsScreen} />
</HomeStack.Navigator>
)
}
function AccountStackNavigator() {
return (
<AccountStack.Navigator screenOptions={{ headerShown: false }}>
<AccountStack.Screen name="Dashboard" component={DashboardScreen} />
<AccountStack.Screen name="Update Profile" component={UpdateProfileScreen} />
</AccountStack.Navigator>
)
}
function AuthStackNavigator() {
return (
<AuthStack.Navigator screenOptions={{ headerShown: false }}>
<AuthStack.Screen name="Login" component={LoginScreen} />
<AuthStack.Screen name="SignUp" component={SignUpScreen} />
<AuthStack.Screen
name="ForgotPassword"
component={ForgotPasswordScreen}
/>
</AuthStack.Navigator>
);
}
function TabNavigator() {
return (
<Tab.Navigator initialRouteName="Home">
<Tab.Screen name="Home" component={HomeStackNavigator} />
<Tab.Screen name="Account" component={AccountStackNavigator} />
</Tab.Navigator>
)
}
const Drawer = createDrawerNavigator<DrawerNavigatorParamsList>();
function DrawerNavigator () {
return (
<Drawer.Navigator
drawerContent={DrawerContent}
>
<Drawer.Screen name="HomeDrawer" component={TabNavigator} />
<Drawer.Screen
name="Auth"
component={AuthStackNavigator}
options={{swipeEnabled: false}}
}}
/>
</Drawer.Navigator>
)
}
Also you may want to disable the Drawer navigator on a specific auth screen. You can just leverage the React Navigation's getFocusedRouteNameFromRoute
function handler like the following:
const drawerAuthScreensDisplay = [
"ForgotPassword",
"Login",
];
function showDrawerNavigator (route: RouteProp<DrawerNavigatorParamsList, keyof DrawerNavigatorParamsList>) {
const routeName = getFocusedRouteNameFromRoute(route);
return Boolean(drawerAuthScreensDisplay.includes(routeName))
}
function DrawerNavigator () {
return (
<Drawer.Navigator
drawerContent={DrawerContent}
>
<Drawer.Screen name="HomeDrawer" component={TabNavigator} />
<Drawer.Screen
name="Auth"
component={AuthStackNavigator}
options={({ route }) => ({
swipeEnabled: showDrawerNavigator(route)
})}
}}
/>
</Drawer.Navigator>
)
}
I hope these help someone struggling to prevent the drawer being swiped on specific stack screens.
Upvotes: 0
Reputation: 8103
The swipeEnabled
property can help, but the drawer could still be triggered for other reasons (for example, an action can programatically open it).
If you want to make sure that the drawer doesn't show at all in some cases, and you are able to detect the condition globally, you can use drawerStyle: { display: 'none' }
in screenOptions
:
const screenOptions = {
drawerStyle: {
display: 'none',
},
// ...
};
<Drawer.Navigator
drawerContent={({ navigation }) => (
<DrawerContent navigation={navigation} />
)}
screenOptions={screenOptions}
>
{'...'}
</Drawer.Navigator>
In my case, I don't want to show the drawer if the user is not authenticated, so I define the display: 'none' in that case.
Upvotes: 0
Reputation: 1206
I have added the navigation setup code for disabling side menu for specific screen, This may helpful for someone.
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
import LoginScreen from '../LoginScreen'
import PasswordScreen from '../PasswordScreen'
import HomeScreen from '../HomeScreen'
const Stack = createStackNavigator()
const Drawer = createDrawerNavigator()
const sideMenuDisabledScreens = ['Login', 'Password']
const DrawerNavigator = () => {
return (
<Drawer.Navigator
screenOptions={{headerShown: false}}
drawerPosition="right"
drawerContent={(props) => <SideMenu {...props} />}
>
<Drawer.Screen
name="Initial"
component={StackNavigator}
options={({ route }) => {
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Login'
if (sideMenuDisabledScreens.includes(routeName))
return ({swipeEnabled: false})
}}
/>
</Drawer.Navigator>
);
}
const StackNavigator = () => {
return (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name='Login' component={LoginScreen}/>
<Stack.Screen name='Password' component={PasswordScreen} options={{gestureEnabled: false}}/>
<Stack.Screen name='Home' component={HomeScreen} />
</Stack.Navigator>
);
}
function MainNavigator() {
return (
<NavigationContainer>
<DrawerNavigator />
</NavigationContainer>
);
}
export default MainNavigator
App.js has the following code
import React, { Component } from 'react';
import MainStackNavigator from './src/navigation/MainStackNavigator';
export default class App extends Component {
render() {
return (
<>
<MainStackNavigator />
</>
);
}
}
Upvotes: 7
Reputation: 355
You can set options per screen using "swipeEnabled" property. Please take a look to related page of docs;
https://reactnavigation.org/docs/drawer-navigator/#options
<Drawer.Navigator initialRouteName="Feed">
<Drawer.Screen
name="Feed"
component={Feed}
options={{ swipeEnabled: false }}
/>
<Drawer.Screen
name="Profile"
component={Profile}
options={{ drawerLabel: 'Profile' }}
/>
</Drawer.Navigator>);}
Upvotes: 17
Reputation: 13462
To disable swipe/gesture in a single route in React Navigation V5:
Import helper to get current route name
import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
Check if the route name is the same as the route you want to disable swipe/gesture
options={({ route }) => {
const routeName = getFocusedRouteNameFromRoute(route);
return {
swipeEnabled: routeName !== 'Profile',
};
}}
Upvotes: 4
Reputation: 192
In v5 u can use <Drawer.Navigator screenOptions={{ gestureEnabled: false }} ...>...</Drawer.Navigator>
Upvotes: 6
Reputation: 370
The issue was that i was using Ignite to generate my project template and the react-navigation version was fixed at 3.0.0. And after watching the last comment at this link I realized that it wasn't any issue with my syntax.
So I deleted my packed.lock.json, yarn.lock, node_modules folder, in package.json I set the version as ^3.0.0 in order to get the latest version.
After all this I did a yarn install for getting a full package update. With this change my react-navigation-drawer went from 1.0.1 to 1.3.0 and this fixed the problem.
Also made some changes to my navigation which now looks like this:
export default class UserNavigation extends React.Component{
render(){
return <Nav />
}
}
const Nav = createAppContainer(
createDrawerNavigator(
{
ProductListScreen: {screen: ProductListScreen},
ProductHistoryScreen: {
screen: ProductHistoryScreen,
navigationOptions:{
drawerLockMode: 'locked-closed'
}
}
}, {
initialRouteName: 'ProductListScreen',
contentComponent: CustomDrawerContentComponent,
}
)
)
Upvotes: 4