react-nativereact-navigationreact-navigation-stackreact-navigation-v5react-navigation-drawer

React-navigation - goBack behaviour in nested navigators (stack inside drawer)


I'm using a stack navigator inside drawer navigator - recently upgraded from v4. Trying to implement custom back button on headerLeft. goBack function on the stack screen is going back on the drawer navigator instead of the stack. I don't know if I'm missing something or if it's a bug on v5. The goBack should go to the previous screen in the stack not the drawer. See the gif below; using the gesture goes back on the stack and the default back button on the header goes back onto the stack too. It's only my custom back button with the problem.

enter image description here

export function BlogsStack({navigation}) {
  return (
    <Stack.Navigator
      initialRouteName={'Blogs'}
      screenOptions={{
        gestureEnabled: true,
        gestureDirection: 'horizontal',
        cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
        headerStyle: {
          borderBottomWidth: 0,
          elevation: 0,
          shadowOpacity: 0,
        },
        headerTintColor: themeVars.headerTintColor,
        headerBackground: () => {
          return <HeaderBackground />;
        },
      }}>
      <Stack.Screen
        name="Blogs"
        component={Blogs}
        options={{
          title: 'Blogs',
          headerTitle: () => (
            <View>
              <HeaderButton title={'Blogs'} />
            </View>
          ),
          headerLeft: () => (
            <TouchableOpacity
              onPress={() => navigation.toggleDrawer()}
              style={drawerStyles.menuIconContainer}>
              <FeatherIcon
                style={drawerStyles.menuIcon}
                name="menu"
                size={themeVars.hamburgerIconSize}
                color={themeVars.hamburgerIconColor}
              />
            </TouchableOpacity>
          ),
          headerRight: () => <View />,
        }}
      />
      <Stack.Screen
        name="BlogSingle"
        component={BlogSingle}
        options={{
          headerTitle: () => (
            <View>
              <HeaderButton title={'Blog'} />
            </View>
          ),
          headerLeft: () => (
            <TouchableOpacity
              onPress={() => navigation.goBack()}
              style={drawerStyles.menuIconContainer}>
              <FeatherIcon
                style={drawerStyles.menuIcon}
                name="chevron-left"
                size={themeVars.hamburgerIconSize}
                color={themeVars.hamburgerIconColor}
              />
            </TouchableOpacity>
          ),
          headerRight: () => <View />,
        }}
      />
    </Stack.Navigator>
  );
}


export class Navigation extends Component {
  constructor(props, context) {
    super(props, context);
  }

  render() {
    return (
      <NavigationContainer ref={navigationRef}>
        <AppDrawer.Navigator
          initialRouteName={'Home'}
          drawerContent={props => <DrawerContent {...props} />}
          drawerContentOptions={{
            labelStyle: {
              fontFamily: themeVars.boldFont,
              color: themeVars.primaryColor,
            },
            activeTintColor: 'black',
            activeBackgroundColor: 'black',
            inactiveTintColor: 'white',
            inactiveBackgroundColor: 'white',
            itemStyle: {
              marginVertical: 0,
              borderWidth: 1,
              borderColor: 'red',
              margin: 0,
              padding: 0,
            },
          }}>
          <AppDrawer.Screen
            name="Home"
            component={HomeStack}
            initialRouteName={'Home'}
            options={{
              drawerLabel: 'Home ',
              drawerIcon: () => (
                <FeatherIcon
                  color={themeVars.primaryColor}
                  name="home"
                  size={themeVars.drawerIconSize}
                />
              ),
            }}
          />
          <AppDrawer.Screen
            initialRouteName="Blogs"
            backBehavior="order"
            name="Blogs"
            component={BlogsStack}
            options={{
              drawerLabel: 'Blogs ',
              drawerIcon: () => (
                <FontAwesome5
                  color={themeVars.primaryColor}
                  name="wordpress"
                  size={themeVars.drawerIconSize}
                />
              ),
            }}
          />
        </AppDrawer.Navigator>
      </NavigationContainer>
    );
  }
}

Solution

  • I sorted out my issue by following the docs. The issue was that I was passing the wrong navigation.

    You need to use the correct navigation prop in your header, i.e. by defining a callback for the options: https://reactnavigation.org/docs/screen-options#options-prop-on-screen

    You're using navigation prop passed from the parent navigator which is a drawer, so the action is performed in the drawer.

    Follow the git issue: https://github.com/react-navigation/react-navigation/issues/8806