I'm very new to React native. I'm going to share my codes here App.js
import React, {Component} from 'react';
import Routes from './src/Routes';
export default class App extends Component {
render() {
return (
<Routes />
);
}
}
index.js
import React, { Component } from 'react';
import { AppRegistry, Dimensions } from 'react-native';
import { createDrawerNavigator } from 'react-navigation';
import App from './App';
import {name as appName} from './app.json';
import SideMenu from './src/SideMenu'
import Routes from './src/Routes';
const drawernav = createDrawerNavigator({
Item1: {
screen: Routes,
}
}, {
contentComponent: SideMenu,
drawerWidth: Dimensions.get('window').width - 120,
});
AppRegistry.registerComponent(appName, () => drawernav);
AppRegistry.registerComponent(appName, () => App);
Routes.js
import React, {Component} from 'react';
import { createStackNavigator, createAppContainer, createDrawerNavigator, DrawerActions } from 'react-navigation';
import Home from './Home';
import Settings from './Settings';
import SideMenu from './SideMenu';
import { Button, Platform, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
const Nav = createStackNavigator({
Home: {
screen: Home,
navigationOptions: ({navigation}) => ({
title: "Home",
headerLeft:(<TouchableOpacity onPress={() => navigation.openDrawer()}>
<Text >Button</Text>
</TouchableOpacity>
),
})
},
Settings: {
screen: Settings,
navigationOptions: ({navigation}) => ({
title: "Settings",
})
},
});
const Routes = createAppContainer(Nav);
export default Routes;
SideNav.js
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import styles from './SideMenu.style';
import {NavigationActions} from 'react-navigation';
import {ScrollView, Text, View} from 'react-native';
import Home from './Home';
import Settings from './Settings';
class SideMenu extends Component {
navigateToScreen = (route) => () => {
const navigateAction = NavigationActions.navigate({
routeName: route
});
this.props.navigation.dispatch(navigateAction);
}
render () {
return (
<View style={styles.container}>
<ScrollView>
<View>
<Text style={styles.sectionHeadingStyle}>
Section 1
</Text>
<View style={styles.navSectionStyle}>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Settings')}>
Page1
</Text>
</View>
</View>
<View>
<Text style={styles.sectionHeadingStyle}>
Section 2
</Text>
<View style={styles.navSectionStyle}>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Home')}>
Page2
</Text>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Settings')}>
Page3
</Text>
</View>
</View>
<View>
<Text style={styles.sectionHeadingStyle}>
Section 3
</Text>
<View style={styles.navSectionStyle}>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Settings')}>
Page4
</Text>
</View>
</View>
</ScrollView>
<View style={styles.footerContainer}>
<Text>This is my fixed footer</Text>
</View>
</View>
);
}
}
SideMenu.propTypes = {
navigation: PropTypes.object
};
export default SideMenu;
Home.js
import React, { Component } from 'react';
import { View, Text, Button } from 'react-native';
export class Home extends Component {
render() {
return (
<View >
<Text>This is the home screen</Text>
<Button onPress={() => this.props.navigation.navigate('Settings')} title="Settings"/>
</View>
)
}
}
export default Home
When I click the button in the header, I get the error
undefined is not a function (evaluating navigation.openDrawer()')
I really dont mean to do this but I'm really desperate right now. I've spent two days trying to figure how to make a side menu and I'm really disappointed in this framework. You wont even spend 5 mins to create a side menu in Ionic. Kindly help on this. Project available on git .git
I'm very new to React native. I'm going to share my codes here App.js
import React, {Component} from 'react';
import Routes from './src/Routes';
export default class App extends Component {
render() {
return (
<Routes />
);
}
}
index.js
import React, { Component } from 'react';
import { AppRegistry, Dimensions } from 'react-native';
import { createDrawerNavigator } from 'react-navigation';
import App from './App';
import {name as appName} from './app.json';
import SideMenu from './src/SideMenu'
import Routes from './src/Routes';
const drawernav = createDrawerNavigator({
Item1: {
screen: Routes,
}
}, {
contentComponent: SideMenu,
drawerWidth: Dimensions.get('window').width - 120,
});
AppRegistry.registerComponent(appName, () => drawernav);
AppRegistry.registerComponent(appName, () => App);
Routes.js
import React, {Component} from 'react';
import { createStackNavigator, createAppContainer, createDrawerNavigator, DrawerActions } from 'react-navigation';
import Home from './Home';
import Settings from './Settings';
import SideMenu from './SideMenu';
import { Button, Platform, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
const Nav = createStackNavigator({
Home: {
screen: Home,
navigationOptions: ({navigation}) => ({
title: "Home",
headerLeft:(<TouchableOpacity onPress={() => navigation.openDrawer()}>
<Text >Button</Text>
</TouchableOpacity>
),
})
},
Settings: {
screen: Settings,
navigationOptions: ({navigation}) => ({
title: "Settings",
})
},
});
const Routes = createAppContainer(Nav);
export default Routes;
SideNav.js
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import styles from './SideMenu.style';
import {NavigationActions} from 'react-navigation';
import {ScrollView, Text, View} from 'react-native';
import Home from './Home';
import Settings from './Settings';
class SideMenu extends Component {
navigateToScreen = (route) => () => {
const navigateAction = NavigationActions.navigate({
routeName: route
});
this.props.navigation.dispatch(navigateAction);
}
render () {
return (
<View style={styles.container}>
<ScrollView>
<View>
<Text style={styles.sectionHeadingStyle}>
Section 1
</Text>
<View style={styles.navSectionStyle}>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Settings')}>
Page1
</Text>
</View>
</View>
<View>
<Text style={styles.sectionHeadingStyle}>
Section 2
</Text>
<View style={styles.navSectionStyle}>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Home')}>
Page2
</Text>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Settings')}>
Page3
</Text>
</View>
</View>
<View>
<Text style={styles.sectionHeadingStyle}>
Section 3
</Text>
<View style={styles.navSectionStyle}>
<Text style={styles.navItemStyle} onPress=
{this.navigateToScreen('Settings')}>
Page4
</Text>
</View>
</View>
</ScrollView>
<View style={styles.footerContainer}>
<Text>This is my fixed footer</Text>
</View>
</View>
);
}
}
SideMenu.propTypes = {
navigation: PropTypes.object
};
export default SideMenu;
Home.js
import React, { Component } from 'react';
import { View, Text, Button } from 'react-native';
export class Home extends Component {
render() {
return (
<View >
<Text>This is the home screen</Text>
<Button onPress={() => this.props.navigation.navigate('Settings')} title="Settings"/>
</View>
)
}
}
export default Home
When I click the button in the header, I get the error
undefined is not a function (evaluating navigation.openDrawer()')
I really dont mean to do this but I'm really desperate right now. I've spent two days trying to figure how to make a side menu and I'm really disappointed in this framework. You wont even spend 5 mins to create a side menu in Ionic. Kindly help on this. Project available on git https://github./yinka1255/react.git
Share Improve this question edited Jan 16, 2019 at 17:50 dentemm 6,3794 gold badges33 silver badges44 bronze badges asked Jan 16, 2019 at 17:36 YinkaYinka 2,0814 gold badges17 silver badges23 bronze badges 1- hi, you still have that error or solved it? – Abolfazl Roshanzamir Commented Apr 21, 2020 at 8:13
4 Answers
Reset to default 1The error
undefined is not a function (evaluating navigation.openDrawer()')
is being thrown because the navigation
prop does not have an openDrawer
method. Instead, you need to use the dispatch
method and the DrawerActions
helper:
import { DrawerActions } from 'react-navigation'
...
const Nav = createStackNavigator({
Home: {
screen: Home,
navigationOptions: ({navigation}) => ({
title: "Home",
headerLeft:(
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
<Text>Button</Text>
</TouchableOpacity>
),
})
},
DrawerActions
has three methods that each return dispatchable actions. openDrawer
, closeDrawer
, and toggleDrawer
which will toggle the Drawer state from open to closed and vice versa. Hope that helps!
undefined is not a function (evaluating navigation.openDrawer()')
DrawerActions from react-navigation
is no longer available.
use import {DrawerActions} from '@react-navigation/native';
<TouchableOpacity
onPress={() => navigation.dispatch(DrawerActions.openDrawer())}
style={{
width: 60,
height: 40,
padding: 10,
paddingLeft: 20,
}}>
<Icon
size={20}
name="bars"
style={{marginLeft: 2}}
color="#fff"
/>
</TouchableOpacity>
import { View, Text, TouchableOpacity } from 'react-native'
import { EvilIcons } from '@expo/vector-icons'
import { useNavigation, DrawerActions } from '@react-navigation/native'
import React from 'react'
const Navbar = () => {
const navigation = useNavigation()
return (
<View>
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
<View>
<EvilIcons name='navicon' color='white' size={40}/>
</View>
</TouchableOpacity>
</View>
)
}
It's not the framework, it's you.
You dont need to use app.js as a dummy ponent, you can directly use the same code of routes.js in your app.js . Wraping a navigator inside a ponent gives problems.
Second, you are using appregistry twice, you shoul use it once, it its going directyl to App.js wich doesn't have a drawer, and is not using drawernav at all, that's why undefined is not a function, there is no drawer .
index.js [the first file react-native looks into]
import { AppRegistry, Dimensions } from 'react-native';
import {name as appName} from './app.json';
import { createDrawerNavigator , createAppContainer } from 'react-navigation';
import SideMenu from './src/SideMenu'
import Routes from './src/Routes';
const drawernav = createDrawerNavigator({
Item1: {
screen: Routes,
}
}, {
contentComponent: SideMenu,
drawerWidth: Dimensions.get('window').width - 120,
});
AppRegistry.registerComponent(appName, () => createAppContainer(drawernav)); //createAppContainer goes in your root navigator, in this case, a drawer
routes.js
import { createStackNavigator } from 'react-navigation';
import Home from './Home';
import Settings from './Settings';
import SideMenu from './SideMenu';
import { Button, Text, TouchableOpacity } from 'react-native';
const Nav = createStackNavigator({
Home: {
screen: Home,
navigationOptions: ({navigation}) => ({
title: "Home",
headerLeft:(<TouchableOpacity onPress={() => navigation.openDrawer()}>
<Text >Button</Text>
</TouchableOpacity>
),
})
},
Settings: {
screen: Settings,
navigationOptions: ({navigation}) => ({
title: "Settings",
})
},
});
export default Nav;
Also, Since you are just displaying one ponent in the drawer navigator (Routes), you should not be nesting the screens inside a stacknavigator, just pass it to drawernavigator and the drawernavigator will switch between them
const drawernav = createDrawerNavigator({
Item1: {
screen: Home,
screen: Settings,
}
}, {
contentComponent: SideMenu,
drawerWidth: Dimensions.get('window').width - 120,
});