Search code examples
javascriptreact-nativereact-navigationreact-navigation-stackreact-navigation-drawer

How to go to initialRoute with react-navigation when exiting a child stack navigator inside a drawer?


I build an app with react-native, expo and react-navigation. I have a main drawer navigator who has in it 2 other stack navigator. One stack navigator have 2 pages; Products and Product. When I click on one product in the Products page, it goes into the Product page. Ben if I click on another link in my drawer navigator, I would like that the Products page's stack navigator would return to it's initialRoute when leaving the stack navigator.

I tried to set the initialState for when I exit the stack navigator, it render the initialState when I click on the navigator link in my drawer navigator, but it doesn't work when I'm in the child page and exit the navigator. When I click again on Products in my drawer, instead of navigate to the Products page, it stayed on Product.

I can create statics links in my drawer navigator and use this.props.navigation.navigate to always go to this.props.navigation.navigate('Products'), but it will be the last thing I want. I would really love that my drawer navigator stays dynamic with what I pass to it.

I tried to this.props.navigation.navigate when the componentWillUnmountlifecycle goes on, but it didn't work.

How can I do this?

Thank you for your help!


Solution

  • Yes it is entirely possible to reset the stack with react-navigation, there is a specific action for this.

    Here is an example when the drawer is in a tab navigation.

    First we define our drawer in MenuDrawer.js, nothing special here:

    import { createDrawerNavigator } from 'react-navigation';
    
    import ProductStack from './ProductStack';
    import OtherStack from './OtherStack';
    
    const MenuDrawer = createDrawerNavigator({
      Product: {
        screen: ProductStack,
        navigationOptions: {
          drawerLabel: 'My products',
        },
      },
      Other: {
        screen: OtherStack,
        navigationOptions: {
          drawerLabel: 'Something else',
        },
      },
    });
    
    
    export default MenuDrawer;
    

    Finally we define our tab navigation, and we use the tabBarOnPress navigation option to listen to any drawer opening and reset the stack if needed:

    import { createBottomTabNavigator, StackActions, NavigationActions } from 'react-navigation';
    
    import MenuDrawer from './MenuDrawer';
    
    const BottomTabs = createBottomTabNavigator({
      Menu: {
        screen: MenuDrawer,
        navigationOptions: {
          title: 'Menu',
          tabBarOnPress: ({ navigation }) => {
            const notResetRoute = navigation.state.routes.find(x => x.index > 0); // Check for stack not positioned at the first screen
            if (notResetRoute) {
              const resetAction = StackActions.reset({ // We reset the stack (cf. documentation)
                index: 0,
                actions: [
                  NavigationActions.navigate({ routeName: notResetRoute.routes[0].routeName }),
                ],
              });
              navigation.dispatch(resetAction);
            }
            navigation.openDrawer(); // Finally we open the drawer
          },
        },
      },
    });
    
    
    export default BottomTabs;
    

    Here the drawer is opened when the user clicks on the corresponding tab. Obviously the same could be made if the drawer is opened differently, for instance through a click on a button in a given screen. The important thing is to reset the stacks at the same time.