React navigation drawer V5
Asked Answered
R

4

5

I'm using react-navigation version 5. I have tab navigation and drawer navigation together.

I'm trying to add an icon in my header to open/close drawer:

here is my custom right header for toggling the drawer:

const HeaderRight = ({ navigation }) => {   
    return (
      <View style={{flexDirection: 'row'}}>
        <TouchableOpacity
        onPress={ () =>{ navigation.toggleDrawer()}}>  //here is the problem
          <Image source={require('./assets/images/icons/drawer.png')}/>
        </TouchableOpacity>
      </View>
    );}

this is my tab navigator:

const Tab = createBottomTabNavigator();
function AppTab() {
  return (
     <Tab.Navigator>         
        <Tab.Screen name="Category" component={Category} />    
        <Tab.Screen name="Home" component={Home}/>
      </Tab.Navigator>
   );}

drawer navigator:

    const Drawer = createDrawerNavigator();  
    function App() {
      return (    
          <Drawer.Navigator>
            <Drawer.Screen name="AppTab" component={AppTab} />
            <Drawer.Screen name="Notifications" component={NotificationsScreen} />
          </Drawer.Navigator>  
      );}

and my stack navigator to theme mix all:

const Stack = createStackNavigator();
  export default function MyStack() {
  return (
    <NavigationContainer>
    <Stack.Navigator
    headerMode="screen"
     screenOptions={{
          headerRight: ({ navigation }) => (<HeaderRight navigation={navigation} />
        ),}} >
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
    </NavigationContainer>
  );
}

when I press the right header icon enter image description here

what I'm missing here? the documents weren't really helpful

note:I have also try using dispatch but it didn't work:

navigation.dispatch(DrawerActions.toggleDrawer())

package.json:

{
  "name": "test",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "@react-native-community/async-storage": "^1.8.0",
    "@react-native-community/masked-view": "^0.1.6",
    "@react-navigation/bottom-tabs": "^5.0.5",
    "@react-navigation/drawer": "^5.0.5",
    "@react-navigation/native": "^5.0.5",
    "@react-navigation/stack": "^5.0.5",
    "moment": "^2.24.0",
    "randomcolor": "^0.5.4",
    "react": "16.9.0",
    "react-native": "0.61.5",
    "react-native-base64": "0.0.2",
    "react-native-gesture-handler": "^1.6.0",
    "react-native-image-slider": "^2.0.3",
    "react-native-reanimated": "^1.7.0",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-screens": "^2.0.0-beta.4",
    "react-native-woocommerce-api": "^1.0.12"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    "@react-native-community/eslint-config": "^0.0.5",
    "babel-jest": "^24.9.0",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "^0.56.0",
    "react-test-renderer": "16.9.0"
  },
  "jest": {
    "preset": "react-native"
  }
}
Raising answered 20/2, 2020 at 9:39 Comment(6)
does settings page contains the drawer? stack navigator should be the root navigatorAscus
no it doesn't .Raising
what is ur navigation structure stack/drawer/tab?Ascus
I have a drawer navigator which one of the screens in the drawer is a tab navigator. I want to toggle drawer from header in each tab.Raising
put drawer navigator in stack navigatorAscus
can you explain more?I have <Stack.Screen name="Home" component={App}/> and App is a drawer navigatorRaising
A
12

i have created an simple example deppending upon what i understood, i hope it helps,

u can use options props of Stack.Screen to render custom right or left button and in button component use useNavigation hook to get navigation prop and toggle the drawer user navigation.dispatch(DrawerActions.toggleDrawer())

import React, {useEffect} from 'react';
import {View, Text, StyleSheet, Image} from 'react-native';
import {NavigationContainer, useNavigation, DrawerActions} from '@react-navigation/native';
import {createDrawerNavigator} from '@react-navigation/drawer';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {createStackNavigator, HeaderBackButton, Header} from '@react-navigation/stack';
import Home from './src/home';
import {TouchableOpacity} from 'react-native-gesture-handler';

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

const TabComponent = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen component={Home} name="Home1" />
      <Tab.Screen component={Home} name="Home2" />
      {/*
       * Rest Screens
       */}
    </Tab.Navigator>
  );
};

const DrawerComponent = () => {
  return (
    <Drawer.Navigator>
      <Drawer.Screen component={TabComponent} name="Main" />
      {/*
       * Rest Screens
       */}
    </Drawer.Navigator>
  );
};

const HeaderLeft = () => {
  const navigation = useNavigation();
  return (
    <View style={{flexDirection: 'row'}}>
      <TouchableOpacity
        onPress={() => {
          navigation.dispatch(DrawerActions.openDrawer());
        }}>
        <Text>Open</Text>
        {/* <Image source={require('./assets/images/icons/drawer.png')} /> */}
      </TouchableOpacity>
    </View>
  );
};

export default () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          options={{
            headerLeft: ({}) => <HeaderLeft />
          }}
          component={DrawerComponent}
          name="Drawer"
        />
        {/*
         * Rest Screens
         */}
      </Stack.Navigator>
    </NavigationContainer>
  );
};
Ascus answered 20/2, 2020 at 12:33 Comment(0)
A
3

Instead of toggleDrawer() use openDrawer()

STEPS

import { DrawerActions } from '@react-navigation/native';

navigation.dispatch(DrawerActions.openDrawer());

If the above function not working try this:

this.props.navigation.openDrawer()

UPDATE CODE

const HeaderRight = ({ navigation }) => {
  return (
    <View style={{ flexDirection: "row" }}>
      <TouchableOpacity
        onPress={() => {
          navigation.dispatch(DrawerActions.openDrawer());
        }}
      >
        <Image source={require("./assets/images/icons/drawer.png")} />
      </TouchableOpacity>
    </View>
  );
};

Make sure you have imported the package before using

Ammo answered 20/2, 2020 at 9:42 Comment(5)
I still get an error : TypeError : undefined is not an object (evaluating 'navigation.dispatch')Raising
Add your package.json to this questionAmmo
I've copied everything from your code but I still get the same error.Raising
Try this -> this.props.navigation.openDrawer() instead of dispatchAmmo
I get this error : undefined is not an object (evaluating '_this.props')Raising
A
0

if this.props.navigation.openDrawer() isnt work, you may try useNavigation.

import { useNavigation } from '@react-navigation/native';

in your header function() add

const navigation = useNavigation();

and add navigation.openDrawer() to onPress

Alethaalethea answered 2/5, 2020 at 8:43 Comment(0)
T
0

this is worck for me !

        headerRight: () => (
          <HeaderButtons HeaderButtonComponent={HeaderButton}> // this is a cutom button
    <Item
      title="Favorite"
      iconName="ios-menu"
      onPress={() => {navigation.navigation.toggleDrawer() }}
    />
  </HeaderButtons>
        ),
Tails answered 25/5, 2020 at 18:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.