react-nativereact-navigationreact-navigation-drawer

React-Native goBack() not navigating to previous screen


I’ve been struggling to get goBack() working inside a drawer navigator and I’m not even sure my whole approach here is correct. I want a side menu that functions independently from the main screens, as the side menu will only handle global settings, sign-out, etc.

In the example below, at “real” sign-in, initialRouteName will be set to either “Screen A” or “Screen B”. (I could therefore land on either Screen A or Screen B.) If I land on A I’ll have the option to navigate to B and may wish to return to A. If I land on B I’ll never need to go to A. I do not want to see A or B in the side menu as they are nothing to do with the global settings. From B I’ll potentially navigate elsewhere. The side menu should work from Screen A and Screen B.

My problem here is, regardless of whether I land on A or B, or whether I navigate to the side menu (Account or Settings), goBack() always takes me to the first screen in the stack (AccountScreen) and not to the screen I’ve just come from.

Any help is gratefully received:

import React from 'react';
import { Text, View, Button, Alert, TextInput } from 'react-native';
import { NavigationContainer, DrawerActions, getFocusedRouteNameFromRoute } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import {
    DrawerItem,
    DrawerItemList,
    DrawerContentScrollView,
    DrawerToggleButton,
} from '@react-navigation/drawer';

import { SignInScreen } from './ui/signinscreen.js';
import { AccountScreen } from './ui/accountscreen.js';
import { SettingsScreen } from './ui/settingsscreen.js';
import { AScreen } from './ui/ascreen.js';
import { BScreen } from './ui/bscreen.js';

const Drawer = createDrawerNavigator();

const HomeDrawer = () => {
    return (
        <Drawer.Navigator
            screenOptions={{
                headerShown: true,
                headerLeft: false,
                headerRight: () => <DrawerToggleButton />,
            }}
            initialRouteName={"Screen A"}
        >
            <Drawer.Screen name="Account" component={AccountScreen}
                options={({ route, navigation }) => (
                    {
                        headerLeft: () => ( <Button title="< Back" onPress={() => navigation.goBack() } />),
                    }
                )}
            />
            <Drawer.Screen name="Settings" component={SettingsScreen}
                options={({ route, navigation }) => (
                    {
                        headerLeft: () => ( <Button title="< Back" onPress={() => navigation.goBack() } />),
                    }
                )}
            />
            <Drawer.Screen name="Screen A" component={AScreen}
                options={{
                    drawerItemStyle: { height: 0 }
                }}
            />
            <Drawer.Screen name="Screen B" component={BScreen}
                options={({ route, navigation }) => (
                    {
                        headerLeft: () => ( <Button title="< Back" onPress={() => navigation.goBack() } />),
                        drawerItemStyle: { height: 0 }
                    }
                )}
            />
        </Drawer.Navigator>
    );
};

const Stack = createStackNavigator();

const App = () => {
    const [isAuthenticated, setIsAuthenticated] = React.useState(false);

    const handleSignIn = () => {
        // Real sign in mechanism
        setIsAuthenticated(true);
    };

    return (
        <NavigationContainer>{
            <Stack.Navigator initialRouteName="Sign In">
                {isAuthenticated ? (
                    <Stack.Group screenOptions={{ headerShown: false }}>
                        <Stack.Screen name="Home" component={HomeDrawer} />
                    </Stack.Group>

                ) : (
                    <Stack.Group screenOptions={{ headerShown: true }}>
                        <Stack.Screen name="Sign In" options={{ title: "Nav Test" }}>
                            {(props) => (
                                <SignInScreen {...props} onSignIn={handleSignIn} />
                            )}
                        </Stack.Screen>
                    </Stack.Group>
                )}
            </Stack.Navigator>
        }</NavigationContainer>
    );
}

export default App;

Solution

  • It was unbelievable simple in the end so for the benefit of anyone else who finds themselves here, all I had to do was add backBehavior="history" to the HomeDrawer screenOptions.

    I found the reference here - https://reactnavigation.org/docs/bottom-tab-navigator/#backbehavior but it seems to equally apply to drawer navigation.