4

I got a React-Navigation 5 drawer menu working using gesture, but I also want to add an icon on the right side of the header to toggle the drawer menu.

I have the navigation setup in my App.js like this:

import {NavigationContainer, DrawerActions} from '@react-navigation/native';
//....... other imports

const HomeStack = createStackNavigator();
const HomeStackScreens = () => (
  <HomeStack.Navigator
    screenOptions={{
      headerStyle: {
        backgroundColor: '#5C6BC0',
      },
      headerTintColor: '#fff',
      headerRight: () => {
        return (
          <TouchableOpacity
            onPress={() => DrawerActions.toggleDrawer()}>
            <Icon name="bars" color="#FFF" size={18} />
          </TouchableOpacity>
        );
      },
    }}>
    <HomeStack.Screen 
      name="Home"
      component={HomeScreen}
      options={{
        header:({scene, previous, navigation}) => {
          return (
            <TouchableOpacity onPress={() => navigation.toggleDrawer()}>
               <Icon name="bars" color="#FFF" size={18} />
            </TouchableOpacity>
          );
        }
      }}
    />
    <HomeStack.Screen name="Login" component={Login} />
    <HomeStack.Screen name="Register" component={Register} />
  </HomeStack.Navigator>
 );

 const ProfileStack = createStackNavigator();
 const ProfileStackScreens = () => (
   <ProfileStack.Navigator>
     <ProfileStack.Screen name="Profile" component={Profile} />
   </ProfileStack.Navigator>
 );

 const SettingStack = createStackNavigator();
 const SettingStackScreens = () => (
   <SettingStack.Navigator>
     <SettingStack.Screen name="Profile" component={Profile} />
   </SettingStack.Navigator>
 );

 const Drawer = createDrawerNavigator();
 const DrawerScreens = () => (
   <Drawer.Navigator>
      <Drawer.Screen name="Home" component={HomeStackScreens} />
      <Drawer.Screen name="Profile" component={ProfileStackScreens} />
      <Drawer.Screen name="Settings" component={SetttingStackScreens} />
   </Drawer.Navigator>
 );

 class MyApp extends React.Component {
   render() {
     return (
       <NavigationContainer>
         <DrawerScreens />
       </NavigationContainer>
     );
   }
 }

 export default MyApp;

All my others screen are in the form "export default class ScreenName extends React.Component". They are imported in App.js to setup the navigation. The initial screen is Home. The icon is showing correctly on the right side of the header. Calling "DrawerActions.toggleDrawer()" directly does nothing.

I tried "this.props.navigation.toggleDrawer()", and it throws error because "this.props" is undefined.

How can I invoke toggleDrawer() with such a navigation setup? Any help is really appreciated!

Mochi08
  • 167
  • 3
  • 15
  • 2
    you can access navigation object like this: https://reactnavigation.org/docs/stack-navigator/#header and then call () => navigation.openDrawer(). Let me know if it works. – getumangon Apr 28 '20 at 05:39
  • Thanks for the response! It works somewhat but I couldn't figure out how to properly implement it. I updated the codes in my original post to add the "header" to the "home" screen setup. The "navigation.toggleDrawer()" part works, but I couldn't figure out how to incorporate the properties like "title", "headerRight" within the "header". In the link, it uses "" which kind of confuses me. Can you give me some pointers? Thanks! – Mochi08 Apr 28 '20 at 20:41
  • In my suggestion what you can do is put headerMode="none" in your Stack.Navigator and make custom and put your predefine left icon, right icon, and title globally. And you can use that header component in every screen. – getumangon Apr 29 '20 at 14:07
  • I think that will require too much change on my codes. I look back at your first comment, and get the idea that if I can somehow receive "navigation" in headerRight then I won't need to change any code. If I get it directly in headerRight I get undefined. But what if I receive it in its parent prop, which is "options" or "screenOptions". I found the documentation for option receiving 'route' here: [link]https://reactnavigation.org/docs/screen-options-resolution[/link]. If it can receive route it can receive navigation too. I tried it and it works! – Mochi08 Apr 29 '20 at 18:20

1 Answers1

3

Here is the final solution I come up with that requires minimal changes to my original code. The key is to receive "navigation" in screenOptions or options, then I can call navigation methods in the children of screenOptions/options.

<HomeStack.Navigator
  screenOptions={({navigation}) => ({
  headerStyle: {
    backgroundColor: '#5C6BC0',
  },
  headerTintColor: '#fff',
  headerRight: () => {
    return (
      <TouchableOpacity
        style={{paddingRight: 8}}
        onPress={() => navigation.toggleDrawer()}>
        <Icon name="bars" color="#FFF" size={18} />
      </TouchableOpacity>
    );
  },
})}>
Mochi08
  • 167
  • 3
  • 15