5
votes

This is the root navigator

export const AppNavigator = StackNavigator({
        Splash: { screen: Splash },
        Dashboard: { screen: DashboardDrawer }
    });

const DashboardDrawer = DrawerNavigator({ DashboardScreen: {
        screen: StackNavigator({
            A: { screen: A },
            B: { screen: B },
            C: { screen: C },
            D: { screen: D },
        }
    }, {
        contentComponent: DashboardDrawerComponent,
        drawerWidth: 280
    });

I have 4 screens - A, B, C, D in my stack. I want to jump from D to A. (or D to any screen) I referred to the following react-navigation documentation-https://reactnavigation.org/docs/navigators/navigation-prop#goBack-Close-the-active-screen-and-move-back

The above doc. states that to go from screen D to screen A (popping D, C, and B) you need to supply a key to goBack FROM, in my case B, like this

navigation.goBack(SCREEN_KEY_B)

So, my question is from where should I get the key for a specific screen? I checked my root navigation object, and it shows me some dynamically generated key for each screen. How can I specify my own keys for the screens?

3

3 Answers

2
votes

It was tricky!

I referred to this section of react-navigation documentation, and have achieved the above! https://reactnavigation.org/docs/routers/#Custom-Navigation-Actions

And this is how,

1. Altered my DrawerNavigator in the question, a little (to fit in the the following stacknavigator)

const DrawerStackNavigator = new StackNavigator({
        A: { screen: A },
        B: { screen: B },
        C: { screen: C },
        D: { screen: D },
    }
});

const DashboardDrawer = DrawerNavigator({
        DashboardScreen: DrawerStackNavigator,
}, { 
       contentComponent: DashboardDrawerComponent,
       drawerWidth: 280
});

2. Dispatched an action in screen D

const {navigation} = this.props;
navigation.dispatch({
    routeName: 'A',
    type: 'GoToRoute',
});

3. Listened to this action on my stack navigator

const defaultGetStateForAction = DrawerStackNavigator.router.getStateForAction;
DrawerStackNavigator.router.getStateForAction = (action, state) => {            
    if (state && action.type === 'GoToRoute') {           
        let index = state.routes.findIndex((item) => {
            return item.routeName === action.routeName
        });
        const routes = state.routes.slice(0, index+1);
        return {
            routes,
            index
        };    
    }       
    return defaultGetStateForAction(action, state);
};
0
votes

Looks like the way they are doing it right now is to save the key of the screen you want to come back through params. So once you are in B and navigate to C, you pass the screen key to C as a param and then when you navigate from C to D you pass the key of B to D as a param.

More info here.

0
votes

I use a setup with NavigatorService as outlined here in the post from unexge.

From the service, I expose the following:

function goBackToRouteWithName(routeName: string) {
  if (!_container) return;
  const route = _getRouteWithName(_container.state.nav, routeName);
  route && _container.dispatch(NavigationActions.back({ key: route.key }));
}

function _getRouteWithName(route, name: string): ?NavigationRouteConfigMap {
  const stack = [];
  stack.push(route);
  while (stack.length > 0) {
    let current = stack.pop();
    if (current.routes) {
      for (let i = 0; i < current.routes.length; i++) {
        if (current.routes[i].routeName === name) {
          //NOTE because of going from, not to!!
          return current.routes[i + 1];
        }
        stack.push(current.routes[i]);
      }
    }
  }
}

this works well for me.