Search code examples
react-nativereact-navigationreact-navigation-stackreact-navigation-v5react-navigation-drawer

React navigation 5 stack navigator and drawer navigator together


Basically I am from react-navigation v4, I am familiar handling the same with SwitchNavigator as bridge, but v5 does no support for SwitchNavigator, so bit struggling to understand the below implementation.

const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();

function AuthenticationStack({ navigation }) {
    return (
        <Stack.Navigator initialRouteName="Home" screenOptions={{headerShown: false}}>
            <Stack.Screen name="Home" component={Home} />
            <Stack.Screen name="Login" component={Login} />
            <Stack.Screen name="Registration" component={Registration} />
        </Stack.Navigator>
    );
}

function UserStack({ navigation }) {
    return (
        <Stack.Navigator initialRouteName="Jobs" screenOptions={{headerShown: false}}>
            <Stack.Screen name="Jobs" component={Profile} />
            <Stack.Screen name="JobDetails" component={JobDetails} />
        </Stack.Navigator>
    );
}

function App() {
    return (
        <NavigationContainer>
            <Drawer.Navigator drawerContent={props => <SideBar { ...props } />}>
                <Drawer.Screen name="Home" component={AuthenticationStack} />
                <Drawer.Screen name="Jobs" component={UserStack} />
            </Drawer.Navigator>
        </NavigationContainer>
    );
}

export default App;

The above code works but have some problems like,

  1. While loading the app, initially the drawer is visible and goes hidden when the app loaded.
  2. I do not want to have drawers for Authentication screens, If I have 2 different navigation without splitting AuthenticationStack and UserStack then I am facing problem while navigating from Login to Profile and vice versa

UPDATE 1

export default() => {
    const [logged, setUser] = React.useState(false);
    return (
        <NavigationContainer>
            {
                logged
                ?
                <DrawerScreen initialParams={{ setUser }} />
                :
                <AuthStackScreen initialParams={{ setUser }} />
            }
        </NavigationContainer>  
    );
}

Now in login.js, I need to update setUser to true, right? If yes how can I access setUser in my login.js file

Update 2

class Login extends Component {
    fetch(login_url, {
            method: "POST",
            headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Accept-Language': 'en-US' },
            body: JSON.stringify(data)
        })
        .then((response) => {
            const success = response.ok;
            const data = response.json();
            return Promise.all([success, data]);
        })
        .then(([success, response]) => {
            var data, userInfo;
            if (success) {
                data = {
                    token: response.token,
                    user: response.user,
                }
    
                if(_storeUserData(response)) {
                    _retrieveUserData().then((userInfo) => {
    
                        this.setState({
                            logged: true,
                            userInfo: userInfo,
                            loading:false,
                            email: '',
                            password: ''
                        });
                        navigate('Profile');
                    })
                    .catch((error) => {
                        // alert(error);
                    });
                }
            }
            this.setState(state_data);
        })
        .catch((error) => {
            alert('Error:'+error);
            this.setState({ loading: false});
        });
}

Solution

  • You can create something similar to the switch navigator by conditionally rendering navigators like below.

    export default function App() {
      const [loggedIn, setLoggedIn] = React.useState(false);
      return (
        <NavigationContainer>
          {loggedIn ? (
            <Drawer.Navigator initialRouteName="Home">
              <Drawer.Screen name="Home" component={HomeScreen} initialParams={{ setLoggedIn }}/>
              <Drawer.Screen name="Notifications" component={NotificationsScreen} />
            </Drawer.Navigator>
          ) : (
            <Stack.Navigator>
              <Stack.Screen
                name="Auth"
                component={AuthScreen}
                initialParams={{ setLoggedIn }}
              />
            </Stack.Navigator>
          )}
        </NavigationContainer>
      );
    }
    

    You can tryout this snack for a working example https://snack.expo.io/@guruparan/switchsample