Search code examples
javascriptreact-nativereact-navigationreact-navigation-drawerreact-navigation-v6

React native drawer navigator not opening


I'm building a react native app and using react navigation v6 library. I've built a react navigator that works fine for the most part, but I'm facing this bug when navigating to a certain page.

I have a stack navigator:

   <NavigationContainer>

      <Stack.Navigator >
        <Stack.Screen name='LandingScreen' component={LandingScreen} options={{headerShown: false}} />
        <Stack.Screen name='LoginScreen' component={LoginScreen} options={{headerShown: false}} />
        <Stack.Screen name='RegisterScreen' component={RegisterScreen} options={{headerShown: false}} />

        <Stack.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} options={{ header: () => <Header/> }} />

        <Stack.Screen name='HomeScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
      </Stack.Navigator>
    </NavigationContainer>

And the drawer navigator:

    <Drawer.Navigator screenOptions={{
        drawerStyle: {
          backgroundColor: 'white',
          zIndex: 100
        },
        drawerPosition: 'right'
      }}>
        <Drawer.Screen name='Search cocktails' component={HomeScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Profile' component={ProfileScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Publish a recipe' component={PublishRecipeScreen} options={{headerShown: false}} />

        <Drawer.Screen name='Favorites' component={FavoritesScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Published recipes' component={PublishedRecipesScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Log out' component={LandingScreen} options={{headerShown: false}} />
    </Drawer.Navigator>

The problem occurs when navigating to CocktailDetailScreen, the thing is the drawer just won't open. The drawer is opened from the header component (which is shared by CocktailDetailScreen, homeScreen and all the screens within the drawer) and to open it I'm using navigation.dispatch(DrawerActions.toggleDrawer()). This works fine on every screen except of this one.

I've figured that If I remove CocktailDetailScreen from the stack navigator and add it to the drawer navigator, then the drawer opens normally. But I don't want this, since this page should only be accessed through other screens, not directly from the "menu"/navigator.

I'm sure this is possible, but I don't get what I'm doing wrong. Maybe I'm not nesting the navigators correctly or the screen shouldn't be in the navigator at all?

Full code is here: https://github.com/coccagerman/mixr


Solution

  • Drawer Navigator is nested inside Stack Navigator, Screens below can access drawer specific actions ( open, close or toggle)

    • Search cocktails
    • Profile
    • Publish a recipe
    • Favorites
    • Published recipes
    • Log out

    due to they are children to a Drawer navigator.

    To make Drawer actions accessible to all screens, the Drawer must be a parent to all navigators.

    Let's refactor our code as below.

    
    const PublicStack = (
      <Stack.Navigator>
        <Stack.Screen
          name="LandingScreen"
          component={LandingScreen}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="LoginScreen"
          component={LoginScreen}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="RegisterScreen"
          component={RegisterScreen}
          options={{ headerShown: false }}
        />
    
        <Stack.Screen
          name="CocktailDetailScreen"
          component={CocktailDetailScreen}
          options={{ header: () => <Header /> }}
        />
    
        <Stack.Screen
          name="HomeScreen"
          component={DrawerNavigator}
          options={{ header: () => <Header /> }}
        />
      </Stack.Navigator>
    );
    
    const ProtectedStack = () => (
      <Stack.Navigator>
        <Stack.Screen
          name="Search cocktails"
          component={HomeScreen}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="Profile"
          component={ProfileScreen}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="Publish a recipe"
          component={PublishRecipeScreen}
          options={{ headerShown: false }}
        />
    
        <Stack.Screen
          name="Favorites"
          component={FavoritesScreen}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="Published recipes"
          component={PublishedRecipesScreen}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="Log out"
          component={LandingScreen}
          options={{ headerShown: false }}
        />
      </Stack.Navigator>
    );
    
    const MainStack = () => {
      // Mocked logic for authentication, Implement actually logic
      const isLoggedIn = true;
    
      return (
        <NavigationContainer>
          <Drawer.Navigator
            screenOptions={{
              drawerStyle: {
                backgroundColor: "white",
                zIndex: 100,
              },
              drawerPosition: "right",
            }}
          >
            {isLoggedIn ? (
              <Drawer.Screen
                name="ProtectedStack"
                component={ProtectedStack}
                options={{ header: () => <Header /> }}
              />
            ) : (
              <Drawer.Screen
                name="PublicStack"
                component={PublicStack}
                options={{ header: () => <Header /> }}
              />
            )}
    
            {/* This screen can be accessible even if when user is not authenticated */}
    
            <Drawer.Screen
              name="CocktailDetailScreen"
              component={CocktailDetailScreen}
              options={{ header: () => <Header /> }}
            />
          </Drawer.Navigator>
        </NavigationContainer>
      );
    };
    
    
    

    This is reference, refactor and structure navigation your requirements.

    Explore more at https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside