最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React-native - undefined is not a function (evaluating navigation.openDrawer()') - Stack Overflow

programmeradmin1浏览0评论

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
Add a ment  | 

4 Answers 4

Reset to default 1

The 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,  
});
发布评论

评论列表(0)

  1. 暂无评论