RESET navigation - Drawer route with animation - react-native

Before all, I have to precise I searched arround as for example https://github.com/react-community/react-navigation/issues/1000 , https://github.com/react-community/react-navigation/issues/307 or even StackOverflow.
I have the following code :
/**** STACKNAVIGATOR 2 ****/
const HomeDrawer = StackNavigator({
HomeDrawerstack: { screen: Home, navigationOptions: { title: 'Accueil', } },
}, { initialRouteName: 'HomeDrawerstack', }
);
/**** STACKNAVIGATOR 3 ****/
const AddIdeaDrawer = StackNavigator({
AddIdeaDrawerRoot: { screen: AddIdea, navigationOptions: { title: 'AddIDea', } },
}, { initialRouteName: 'AddIdeaDrawerRoot', }
);
/**** DRAWERNAVIGATOR ****/
const DrawerRoutes = {
HomeRoot: {
screen: HomeDrawer,
navigationOptions: {
title: 'Home',
},
},
AddIdea: {
screen: AddIdeaDrawer
navigationOptions: {
title: 'Add an idea',
},
},
};
const DrawerOptions = {
initialRouteName: 'HomeRoot',
contentComponent: CustomDrawerContentComponent,
drawerWidth: 300,
};
export const Drawer = DrawerNavigator(DrawerRoutes, DrawerOptions);
/**** STACKNAVIGATOR 1 ****/
export const Navigation = StackNavigator({
HomeDrawerRoot: { screen: Drawer, navigationOptions: { header: null } },
OtherRoot: { screen: Contacts, navigationOptions: { /** **/ } },
}, { initialRouteName: 'HomeDrawerRoot', }
);
What I have tried
Currently, I'm trying to navigate from HomeDrawerstack to AddIdeaDrawerRoot with the StackNavigator animation and preventing the user to go back.
I have tried different solutions I have found on the different issues but any of them solve this problem.
First try :
navigate('AddIdea',)}
The app goes to AddIdea perfectly. However, the user can go back (that's normal I don't use RESET) and there is no animation. The AddIdea screen appears like that without any transition.
Second try :
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: 'AddIdea',})
]
})
It doesn't work.
The logs prints : There is no route defined for key AddIdea. Must be one of: 'HomeDrawerstack'
Third try :
I read on an another issue https://github.com/react-community/react-navigation/issues/#1127 which explains that the key:null was the solution. So I tried the following action :
NavigationActions.reset({
index: 0,
key: null,
actions: [
NavigationActions.navigate({
routeName: 'HomeDrawerRoot',
action: NavigationActions.navigate({ routeName: 'AddIdea',}),
})
]
})
The app goes well to AddIdea. However, still with the possibility of going back to the last page (Home) and without animation.
Fourth try :
navigate({
routeName: 'HomeDrawerRoot',
action: NavigationActions.navigate({
routeName: 'AddIdea', action: NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: AddIdeaDrawerRoot
]
})
})
})
It doesn't work. Printing : There is no route defined for key AddIdeaDrawerRoot. Must be one of: 'HomeDrawerstack'
What I'm trying to do
The only thing I want is going from HomeDrawerstack (Home screen) to AddIdeaDrawerRoot (AddIdea screen). With an animation like the StackNavigator animation and preventing the user of going back. (Disable Back action).
After reading a lot of issues, I didn't find any solutions. Is it a forget of the react-navigation ? Or I'm the problem ?! Thanks in advance.
My current configuration
| software | version
| ---------------- | -------
| react-navigation | ^1.0.0-beta.11
| react-native | 0.45.1
| node | 7.4.0
| npm or yarn | 0.24.5

I had similar problems and could not find a good example app. My navigation in my app crashed the app which was very frustrating. In the end I found a good working project to base my code on: https://github.com/paraswatts/DrawerNavigatorReactNative/
This project has working navigation with both tabs and drawers with no crashes and clean code. I hope it can help you.

Related

How to nested navigate between bottom tabs in React Navigation 6?

Given the structure:
Bottom tabs with lazy: false
TabOne
MainScreen
TabTwo
MainScreen
LevelTwoScreen
LevelThreeScreen
How I can navigate from TabOne -> MainScreen to get the route: TabTwo -> MainScreen -> LevelTwoScreen -> LevelThreeScreen?
Below code dont work, just navigates to TabTwoLevelTwoScreen:
navigation.navigate('TabTwoLevelTwoScreen', {
screen: 'TabTwoLevelThreeScreen',
})
I tried this structure too, not sucess:
Bottom tabs with lazy: false
TabOne
MainScreen
TabTwo
MainScreen
LevelTwoScreen
TabTwoNestedNavigator
LevelThreeScreen
This question started as a issue, see more here.
Thanks!
As said by #RajendranNadar, I'll go with the reset option:
navigation.reset({
routes: [
{
name: 'TabTwo',
state: {
routes: [
{ name: 'MainScreen' },
{ name: 'LevelTwoScreen' },
{ name: 'LevelThreeScreen' },
],
},
},
],
})
You will need to use the nested navigator as you have, but you need to start from the top and work down. Reference https://reactnavigation.org/docs/nesting-navigators#passing-params-to-a-screen-in-a-nested-navigator
navigation.navigate('TabTwo', {
screen: 'TabTwoNestedNavigator',
params: {
screen: 'LevelThreeScreen',
},
})
This answer is still relevant. I think you are confused about how the nested navigator works. In your snack you are navigating to pages that don't exist. Updating your code to the following makes it work.
<Button
title="Navigate to Tab Two - Level Three Screen"
onPress={() =>
navigation.navigate('TabTwo', {
screen: 'TabTwoNestedNavigator',
params: {
screen: 'TabTwoLevelThreeScreen'
},
})
}
/>
Snack: https://snack.expo.dev/#halecolin1/nested-navigation-between-bottom-tabs-does-not-works-in-react-navigation-6

How to handel the routing of screens of createStackNavigator nested inside createDrawerNavigator?

I have screens in stacknavigator which are nested inside DrawerNavigator. I wanted to restart the screens in DrawerNavigator when clicked.
System flow Architecture:
App.js::
StackNavigator:
Login.js
ScreensSetup.js
ScreensSetup.js consists the following::
a. Stack screens as:
const FirstStackNavigator = createStackNavigator({
First: {
screen: Dashboard,
},
});
const SecondStackNavigator = createStackNavigator({
Second: {
screen: Workorders,
},
});
b. DrawerNavigator nested with above stacked screens as:
const DrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: FirstStackNavigator,
},
Workorders: {
screen: SecondStackNavigator,
},
},
{
contentComponent: DrawerContent ,
initialRouteName: 'Dashboard',
});
I am able to navigate to "Workorders" from "ScreensSetup" by:
this.props.navigation.navigate('Workorders');
This works perfectly.
But I need to restart the screen. So, I used:
For reseting ScreensSetup:
const navigateAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "ScreensSetup" })],
});
this.props.navigation.dispatch(navigateAction);
This works perfectly.
For reseting Workorders:
const navigateAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Workorders" })],
});
this.props.navigation.dispatch(navigateAction);
This gives me error:
Error: Error: There is no route defined for key Workorders.
│ Must be one of: 'Login','ScreensSetup'
I simply wanted to reset the screen when clicked on menus on drawer naviagtor. I am completely messed up with this navigation. Any help would be appreciated. Thank You.
If you want to close all screens and go back to the beginning, use the popToTop'function.
The popToTop action takes you back to the first screen in the stack, dismissing all the others. It's functionally identical to StackActions.pop({n: currentIndex}).
Usage
import { StackActions } from 'react-navigation';
this.props.navigation.dispatch(StackActions.popToTop());

No route found for key in stack navigator in react native

I am making a react native project which got an error for no route found in stack navigator.First of all here is my code for navigation of my app.
const RootStack = createStackNavigator({
Splash : { screen: Splash },
ModelProfile: { screen: ModelProfile},
HomeModel: {screen: modeldrawerNavigator},
EnterOtp : { screen: EnterOtp},
OtpChangePassword : { screen: OtpChangePassword},
}, {
headerMode: 'none',
initialRouteName: 'Splash'
})
const AppNavigator = createAppContainer(RootStack)
export default AppNavigator;
Now the code for modelDrawerNavigator is
const modeldrawerNavigator = createDrawerNavigator(
{
HomeScreen: { screen: homeStack},
EditProfile : { screen: profileStack},
BuyStar : { screen: StarStack},
Notifications : { screen: nStackmodel},
ResetPassword : { screen: ResetPassword},
},
{
initialRouteName: 'HomeScreen',
gesturesEnabled: true,
contentComponent: props => <DrawerModel {...props} />
},
);
And code for StarStack is
const StarStack = createStackNavigator({
Buy : { screen: BuyStars},
PaymentMode : { screen: PaymentMode},
}, {
headerMode: 'none',
initialRouteName: 'Buy'
});
Now when navigating inside drawer i want to clear stack to position 0.
<TouchableOpacity
onPress={() => {
this.props.navigation.navigate('BuyStar');
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Buy' })],
});
this.props.navigation.dispatch(resetAction);
}}
>
<Text style={styles.drawertext}>Buy Stars</Text>
</TouchableOpacity>
Above code is what produces an error that
No route defined for key 'Buy',Must be one of 'Splash','EnterOtp' etc.
I am stuck in this situation . Please help me to resolve this issue.
Thanks in advance .
It seems like the issue is your code is attempting to navigate the root navigator (Splash and EnterOp are both keys on this navigator). According to the docs:
key - string or null - optional - If set, the navigator with the given key will reset. If null, the root navigator will reset.
So maybe you can try adding the key param to your reset action:
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Buy' })],
key: 'BuyStar',
});
Here are some more resources that may help:
SO answer
Github Issue
Note that the implementation will likely depend on if you're using React Navigation 3.0+ or one of the earlier versions.
EDIT
The supplied key should be BuyStar - you're trying to navigate to the route Buy, which exists in the StarStack navigator. The StarStack navigator is located in the drawer navigator, so the key of this navigator is found in its keys:
const modeldrawerNavigator = createDrawerNavigator({
...
BuyStar : { screen: StarStack },
...
The key should be the id of the navigator that contains the route you're trying to navigate to.

Back button handler working on every screen after changing drawer navigator in react - native

I am making a react native application in which there can be two type of user model and member.Now each having different drawer navigator as both having different data and both these drawer are inside a main stack navigator which is main navigator for the application. Now in both the both the drawer navigator .
const RootStack = createStackNavigator({
Splash : { screen: Splash },
PrivacyPolicy : { screen: PrivacyPolicy},
Welcome : { screen: Welcome },
Login : { screen: Login },
HomeMember: {screen: memberdrawerNavigator},
HomeModel: {screen: modeldrawerNavigator},
OtpChangePassword : { screen: OtpChangePassword},
}, {
headerMode: 'none',
initialRouteName: 'Splash'
})
I have a homepage different for both the member type and in both the home page i have implemented the back handler like this.
handleBackWithAlert = () => {
if (this.props.isFocused) {
if(this.state.loading_status){
this.setState({loading_status:false})
}
else{
Alert.alert(
'Exit App',
'Exiting the application?',
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel'
},
{
text: 'OK',
onPress: () => BackHandler.exitApp()
}
],
{
cancelable: false
}
);
}
return true;
}
}
componentWillMount() {
BackHandler.addEventListener('hardwareBackPress',this.handleBackWithAlert);
//this.props.navigation.dispatch(DrawerActions.closeDrawer());
this.props.navigation.closeDrawer();
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackWithAlert);
}
Since i wanted to check back handling on only specific page so i exported my component like this.
export default withNavigationFocus(HomePage);
Now what the problem is that suppose i am using member account and after that i logout and then login with model account then this back handler is working on every screen why ? And if i close or kill that app without logout and restart then this problem disappears.
Here is my code called on logout
AsyncStorage.clear()
ToastAndroid.show("Logged Out Successfully !",ToastAndroid.SHORT);
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Welcome' })],
});
this.props.navigation.dispatch(resetAction);
Kindly help me to solve this problem. Thanks in advance.
According to my understanding, something is wrong with your BackHandler listeners. maybe you're not removing BackHandler listener on componentWillUnmount?

Reset react-navigation Stack from Drawer

A lot of issues opened on official react-navigation github: https://github.com/react-community/react-navigation/issues but no one gives a real solution, including one post saying "look at this problem, a lot of issues": https://github.com/react-community/react-navigation/issues/691 without answer.
Basically: I have a DrawerNavigator with some nested StackNavigator.
export const MainNavigator = DrawerNavigator(
{
OrderNew: {
screen: OrderNew,
navigationOptions: {
drawerLabel: DrawerLabel('New Order')
}
},
Orders: {
screen: OrderNavigator, //a StackNavigator
navigationOptions: {
drawerLabel: DrawerLabel('Orders')
}
},
MenuNavigator: {
screen: MenuNavigator, //a StackNavigator
navigationOptions: {
drawerLabel: DrawerLabel('Menu')
}
},
//more screens...
{
initialRouteName: 'Orders',
drawerPosition: 'right',
contentComponent: props => <ScrollView style={{backgroundColor: 'rgba(227, 100, 29, .95)'}}><DrawerMenu state={props} /></ScrollView>,
}
);
So, I'm passing a contentComponent with my own menu component. My idea is to overwrite the onItemPress event of DrawerItems component and put my logic here.
What I want is: I would like to reset MenuNavigator (and other stack screens) every time users press that item. I just can't achieve this. As i said, I tried a lot of code. Actually, it's like this:
onItemPress={
router => {
const navigateAction = NavigationActions.navigate({
routeName: router.route.routeName,
});
this.props.state.navigation.dispatch(navigateAction);
}
}
The above code works, I can navigate through drawer items. Now, in my head, I just should pass an subaction resetting to the first item on navigator. So I tried:
onItemPress={
router => {
const navigateAction = NavigationActions.navigate({
routeName: router.route.routeName,
action: NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: router.route.routes[0].routeName}),
]
})
});
this.props.state.navigation.dispatch(navigateAction);
}
}
And explodes an error:
There is no route defined for key Menu.
Must be one of: 'Orders','OrderClient'
Summarizing: how could I reset StackNavigator when I do navigate to another DrawerNavigator's item?
You are missing key: null.
Navigation actions should be like this.
action: NavigationActions.reset({
index: 0,
key: null,
actions: [
NavigationActions.navigate({routeName: router.route.routes[0].routeName}),
]
})