Disabling gesture in react-navigation 5 - react-native

I'm creating a project and Initially, it has two stack screens. SettingScreen and ChangePasswordScreen and the one drawer.
export const SettingStackScreen = ({ navigation }) => (
<SettingStack.Navigator>
<SettingStack.Screen
name="Settings"
component={SettingScreen}
/>
<SettingStack.Screen
name="ChangePassword"
component={ChangePasswordScreen}
/>
</SettingStack.Navigator>
);
app.js
<Drawer.Navigator
drawerContent={(props) => <DrawerContent {...props} />}
>
<Drawer.Screen name="Settings" component={SettingStackScreen} />
</Drawer.Navigator>
using this code Drawer is accessible on both screen but I want to access drawer only first screen of SettingStackScreen not on others screen.
I tried gestureEnabled but it disabling the drawer swipe gesture in the both screen.

give this a go:
<Drawer.Navigator
drawerContent={(props) => <DrawerContent {...props} />
edgeWidth={-1} // don't allow slide-to-open
>
<Drawer.Screen name="Settings" component={SettingStackScreen} />
</Drawer.Navigator>
from the docs:
edgeWidth
Allows for defining how far from the edge of the content view the
swipe gesture should activate.
This is not supported on Web.
If you go with this solution you're gonna need a burger menu or something that opens the drawer menu, something like:
<BurgerMenuButton onPress={() => navigation.toggleDrawer()} />

Related

How to minimize React Native Navigation Modal?

How to minimize a modal within a Stack Navigator in React Native so that the model still shows as a small bar at the bottom of the screen and stays even when switching tabs (like in the pictures I attached).
Picture of Modal opened
Picture of Modal miminized
Currently I have built a Bottom Navigation Tab Bar and within this Tab Navigator I have a Stack Navigator where the Modal can be opened.
<Tab.Navigator initialRouteName="Session">
<Tab.Screen name="Social">{() => <Social />}</Tab.Screen>
<Tab.Screen name="History">{() => <History />}</Tab.Screen>
<Tab.Screen name="Session" options={{headerShown: false}}>
{() => (
<Stack.Navigator>
<Stack.Screen name="Start Session">
{() => <StartSession navigate={navigate} />}
</Stack.Screen>
<Stack.Screen
name="New Template"
options={{
presentation: 'containedModal',
}}>
{() => <AddTemplate />}
</Stack.Screen>
</Stack.Navigator>
)}
</Tab.Screen>
<Tab.Screen name="Activities">{() => <Activities />}</Tab.Screen>
<Tab.Screen name="Profile">
{() => <Profile setUser={setUser} setUserCreds={setUserCreds} />}
</Tab.Screen>
</Tab.Navigator>
You can achieve this using a bottom sheet instead of using a modal from react native navigation.
Something like:
https://www.npmjs.com/package/#gorhom/bottom-sheet

React Navigation 6.x pressing back button takes you back to initial screen

I have just moved from React Native 5.x to 6.x and now my Navigation stack is giving me issues. When I navigate a few screens deep in my drawer navigator, and then press the back button on android (haven't tried IOS yes), it leads me right back to my first screen. My Navigation stack is as follows
<NavigationContainer theme={MyTheme}>
<Drawer.Navigator
initialRouteName="NewsFeed"
drawerContent={(props) => <SideNav {...props} />}
screenOptions={{ headerShown: true, header: (options) => <TopNav options={options} /> }}
>
<Drawer.Screen name="NewsFeed" component={NewsFeedScreen} />
<Drawer.Screen name="Post" component={PostScreen} />
<Drawer.Screen name="Users" component={UsersScreen} />
<Drawer.Screen name="User" component={UserScreen} />
...
</Drawer.Navigator>
</NavigationContainer>
I'm unsure what the issue is and haven't found any answers anywhere. Some say to wrap each screen in it's Stack navigator, others say it's a bad idea.
I am not sure if this is what you are asking for, but as for changes listed in the React Navigation Upgrading from 5.x help page:
The default value for backBehavior is now firstRoute for tabs and
drawer
and then:
To preserve old behavior, you can pass backBehavior="history" prop
to the navigators
So you can properly set backBehavior prop in your code like below:
<NavigationContainer theme={MyTheme}>
<Drawer.Navigator
initialRouteName="NewsFeed"
drawerContent={(props) => <SideNav {...props} />}
screenOptions={{ headerShown: true, header: (options) => <TopNav options={options} /> }}
backBehavior="history" // <-- ADDED PROP
>
...
</NavigationContainer>

How can I create a custom navigation drawer in react-native using react-navigation v5?

I am looking to create a custom drawer navigator with a few expandable list views with a few hidden routes.
E.g.
Home
Main1
Hidden 1
hid a
hid b
Hidden 2
hid a
hid b
Where hid a and hid b would be hidden behind hidden 1 or hidden 2. When hidden 1 or hidden 2 is clicked or touched the hid a/hid b would be displayed.
This is what I have so far --
Main.js:
export default function MainScreen({ navigation }){
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName='Home' drawerContent={props => <Menu {... props} />}>
<Drawer.Screen name=".." options={{drawerIcon: config => <Icon name=".." size={22} color="#000"></Icon>}} component={HomeScreen} />
<Drawer.Screen name="Ex1" component={Ex1} />
<Drawer.Screen name="Ex2" component={Ex2} />
<Drawer.Screen name="Ex3" component={Ex3} />
<Drawer.Screen name="Ex4" component={Ex4} />
<Drawer.Screen name="Ex5" component={Ex5} options={{
title:"..",
drawerIcon: config => <Icon
size={22}
name='..'></Icon>
}} />
</Drawer.Navigator>
</NavigationContainer>
)
}
Menu.js:
const Menu = (props) => {
return (
<SafeAreaView style={{flex: 1}}>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
</DrawerContentScrollView>
</SafeAreaView>
);
};
And I'm looking to split out DrawerItemList so I can display a few of my routes within a dropdown.
Much of the code in the samples above has been sanitised because a lot of it is commercially sensitive but I can assure you my component names etc are much better in the actual code.
Any suggestions or comments would be much appreciated.
I have just started working with react-native so bare with me.
If you need any more info, please don't hesitate to comment and ask.
Thanks in advance.
Solution was to use #eliav2/react-native-collapsible-view for the collapsible view with DrawerItems inside.

React Native App - react-navigation v5 can't unmount on blur

I need screen to unmount whenever it goes out of focus. I am using a custom drawer and using props unmountOnBlur={true} and options={{unmountOnBlur: true} but its not working. What am i doing wrong or is there another way to accomplish this? I appreciate any help. Here is the relevant code:
<Drawer.Navigator drawerContent={(props) => <CustomDrawer {...props} />}>
<Drawer.Screen
name='Client Profile'
component={ProfileStackNavigator}
unmountOnBlur={true}
options={{unmountOnBlur: true}}
/>
</Drawer.Navigator>
Here is code on CustomDrawer.js :
<DrawerContentScrollView {...props} >
<DrawerItem
label='Profile'
onPress={() => props.navigation.navigate('Client Profile')}
unmountOnBlur={true}
options={{unmountOnBlur: true}}
/>
</DrawerContentScrollView>

React native: How can I have multiple drawer navigator links point to screens within the same stack navigator

I am new to react native and I haven't seen this question asked by anyone or haven't found a way around this.
Using react navigation 5 with expo.
Currently I have a the following app structure:
Stack navigator inside of drawer navigator.
Example of page structure:
Drawer Navigator ( links ):
Home (RouteStack)
Screen 1
Screen 2
Screen 3
RouteStack( screens) :
Home ( initial route )
Screen 1
Screen 2
Screen 4
How can I get Screen 1/Screen 2 link in drawer navigator load RouteStack: Screen 1/Screen 2?
These links are provided to easily jump to the required screen.
Need some guidance on how to achieve this.
I have thought of the possibility of drawer inside of stack, but there are screens inside of drawer that may not be listed in the stack. Hence, went with stack inside of drawer.
I have also tried to do a navigation.navigate(route.name) inside of RouteStack
Sample code:
Drawer navigator:
<NavigationContainer>
<Drawer.Navigator drawerContent={(props, navigation) => <CustomDrawerContent {...props} {...navigation} />}>
<Drawer.Screen name="Home" component={RouteStack} />
<Drawer.Screen name="MyItems" component={RouteStack} />
<Drawer.Screen name="ContactRep" component={RouteStack} />
<Drawer.Screen name="Settings" component={SettingInfo} />
</Drawer.Navigator>
</NavigationContainer>
Stack navigator (RouteStack) looks like this:
<Stack.Navigator
initialRouteName="Home"
screenOptions={{ gestureEnabled: false, headerTitleAlign: 'auto' }}
// headerMode="float"
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: '',
headerStyle: {
backgroundColor: '#fff',
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'bold'
},
headerLeft: props => <HeaderLeftMenu {...props} />,
headerRight: props => <HeaderRightMenu {...props} />,
headerTitle: props => <HeaderTitle {...props} />
}}
/>
<Stack.Screen
name="ContactRep"
component={ContactRep}
options={{ headerTitle: props => <HeaderTitle {...props} /> }}
/>
<Stack.Screen
name="MyItems"
component={MyItems}
options={{ headerTitle: (props, navigation) => <HeaderTitle {...props} /> }}
/>
</Stack.Navigator>
Thanks in advance and help is appreciated.
Your method is fine. But to clarify your ideas I will give you an example.
Assume I have a main Drawer. In that drawer I can navigate to 2 different screens. Inside those screens, I can navigate and do diferent things (like going to sub-screens), but never go outside the drawer.
To do this, we would have to created nested navigators. This meaning, one type of navigator if going to be inside another one. In our case of example:
<Papa Drawer>
<Screen 1 component={StackSon1}>
<Screen 2 component={StackSon2}>
<Papa Drawer>
And then StackSon1, for example, will look like this:
StackSon = () => {
return (
<Stack.Navigator>
<Stack.Screen>
<Stack.Screen>
...
)
}
React Navigation will also handle every drawer separately, meaning that you don't have to worry about the user creating an infinite chain of open screens.
Also, remember that, when we Nest navigators using a function (like I did) we must use return (or the simplified version of return with just parenthesis)
Hope it helps.