react native navigator:Undefined is not an object(

2019-07-07 20:47发布

问题:

I'm not able to understand how to implement navigation in react-native. as per the doc i have installed the plugin and integrated the code but it keeps giving the error

Undefined is not an object(evaluating this.props.navigation.navigate)

Below is the index.android.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

import Login from './src/pages/Login';
import Home from './src/pages/Home';

import { StackNavigator } from 'react-navigation';

export default class ECart extends Component {
  render() {
    return (
      <App />
    );
  }
}

const App = StackNavigator({
Login:{screen:Login},
Home: {screen: Home}
});



const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('ECart', () => ECart);

The Login page

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  Image,
  TextInput,
  Alert,
  Button,
  TouchableOpacity
} from 'react-native';

import { StackNavigator } from 'react-navigation';

import Home from './Home';


export default class Login extends Component {



    constructor(props) {
         super(props);
        this.state = {};
        this.onButtonPress=this.onButtonPress.bind(this);

    }


    onButtonPress= () => {
       alert("ok");
        const { navigate } = this.props.navigation;
        navigate(Home);
        };

    render() {

    return (
        <View style={styles.container}>

                <View style={{justifyContent: 'center',alignItems: 'center',height:250}}>
                    <Image style={{}} source={require('../img/ic_launcher.png')} />
                </View>
              <View style={styles.wrapper}>

                    <View style={styles.inputWrap}>
                        <View style={styles.iconWrap}>
                        <Image style={styles.icon} source={require('../img/icon/ic_email.png')}/>
                        </View>

                        <TextInput
                          style={styles.input}
                          placeholder="Username"
                          underlineColorAndroid="transparent"
                          placeholderTextColor="#939598"
                        />

                    </View>

                    <View style={styles.inputWrap}>

                        <View style={styles.iconWrap}>
                          <Image style={styles.icon} source={require('../img/icon/ic_lock.png')}/>
                        </View>
                        <TextInput
                          style={styles.input}
                          placeholder="Password"
                          secureTextEntry
                          underlineColorAndroid="transparent"
                          placeholderTextColor="#939598"
                        />

                    </View>

                    <TouchableOpacity
                      activeOpacity={0.5}
                      onPress={this.onButtonPress}>
                      <View style={styles.button}>
                          <Text style={styles.buttonText}>Login</Text>
                      </View>
                    </TouchableOpacity>

                    <TouchableOpacity activeOpacity={0.5}>
                      <View style={styles.textWrap}>
                          <Text>Forgot Password.</Text><Text>Reset here</Text>
                      </View>
                    </TouchableOpacity>

              </View>

                <View style={styles.bottomTextWrap}>
                    <Text style={{}}> By clicking Sign In, you agree to our Terms and that you have read our Data Policy, including our Cookie Use.
                    </Text>
                </View>

              <View style={styles.bottomTextWrap}>
               <Text> Copyright  2017 Suyati Technologies
               </Text>
             </View>

        </View>



    );
  }

}

const styles= StyleSheet.create({
  container:{
    flex:1,
    backgroundColor: '#FFFFFF'
  },

  inputWrap:{
    flexDirection:"row",
    marginVertical:10,
    height:50,
    borderWidth:1,
    borderColor:'#939598',
    backgroundColor:'transparent',
  },
  textWrap:{
    flexDirection:"row",
    backgroundColor:'transparent',
    justifyContent:'center',
    alignItems:'center',
    marginVertical:10,
    paddingHorizontal:20
  },
  bottomTextWrap:{
    flex:1,
    flexDirection:"row",
    backgroundColor:'transparent',
    justifyContent: 'center',
    alignItems:'flex-end',
    marginVertical:10
  },
  text:{
    justifyContent:'center',
    alignItems:'center'
  },

  input:{
    flex:1,
    paddingHorizontal:10,
    backgroundColor:"transparent",
    color:'#939598'
  },
  wrapper:{
    paddingHorizontal:30
  },
  iconWrap  :{
    paddingHorizontal:7,
    justifyContent:'center',
    alignItems:'center',
    borderColor:'#939598'
  },
  icon:{
    width:20,
    height:20
  },
  button:{
    backgroundColor:'#13AFBC',
    paddingVertical:10,
    marginVertical:10,
    justifyContent:'center',
    alignItems:'center'
  },
  buttonText:{
    color:'#FFFFFF',
    fontSize:18
  }
})

I'm trying to navigate to the home screen. I'm finding react-native a bit difficult. If anyone could guide me in the right direction it will be very helpful as i'm stuck at it and need a new approach.

EDIT-I changed the code but still it wont navigate.I get the alert but it stays on the loginpage

Thanks!

回答1:

It seems that you have copy-pasted code from different sources(maybe tutorials) and hope it will work, but usually it doesn't. In your code you have several mistakes.

First of all, in index.android.js file you have ECart component, which is passed to AppRegistry.registerComponent() function. So, this component is a starting point for you application. You also have App variable, which is actually also a component, but you never use it. So now, your app doesn't use react-navigation, as it is not included anyhow. In order to use navigation library, you have to pass it to the app registry on some level. For example like this

const App = StackNavigator({
   Login: {screen: Login},
   Home: {screen: Home},
});

export default class ECart extends Component {
  render() {
    return (
      <App />
    );
  }
}

This way, Ecart is passed to AppRegistry, and it has App (navigation component), which will handle navigations. Because App is responsible for navigation, you should declare your 'routes' and corresponding components that navigation component, like i included Login Screen above. Because Login is first in your StackNavigator declaration, it will be first screen when app is loaded.

Now, every compononent that you passed through StackNavigator will have navigation prop, passed by react-navigation. With that prop, you can navigate to other screens in your app. So, because you in your code Login component is not passed to StackNavigator, this.props.navigation will be undefined. And when you try to access this.props.navigation.navigate, it will throw an error, where it says, that undefined is not an object.This explains your main error, but it is not only error in the code you paste here.

In your Login component, you have

onButtonPress= () => {
    navigate(Home, { name: 'Jane' });
};

which calls navigate function, but it is not declared anyware. So, when you will resolve first error, you will see another error when you press your button, Undefined is not a function. So, to solve this you have to do two things. First, declare navigate function, second bind onButtonPress method.

onButtonPress() {
    const { navigate } = this.props.navigation; 
    navigate('Home', { name: 'Jane' });
};

and bind this method like

constructor(props) {
    super(props);
    this.state = {};

    this.onButtonPress=this.onButtonPress.bind(this);
}

If you are thinking, what the hell is binding, take a look at this video