简体   繁体   中英

undefined is not an object (evaluating 'this.props.navigation")

My navigation suddenly broke down. So there are 3 screens/components, I am using react-navigation to navigate between them. First screen is to enter mobile phone number and password, it is sent to api, and some data is saved into state and passed to second screen , where i am enter code from sms and send another request to api, if response.status == 200, it goes to third screen . Navigation from 1st screen to 2nd works, but from 2nd to third is not. Error occurs when i am going to third screen.

FirstPage.js

export default class FirstPage extends React.Component {
 constructor(props) {
super(props);
this.state = {
  text: '',
  password: '',
  password2: ''
}
}
 state = {
uuid: null
}

 getCode(text, psw) {
   fetch('url', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  },
    body: JSON.stringify({"telephone": text, "password": psw})
  })
  .then(response => response.json())
  .then(response => {
    let uuid = response['data']['id'];
    this.setState({uuid});
    this
      .props
      .navigation
      .navigate('SecondPage', {uuid});
  })
  };

   render() {
return (
  <View
    style={{
    flex: 1,
    justifyContent: "center",
    alignItems: "center"
  }}>
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <View
        style={{
        width: 200,
        height: 60,
        borderColor: 'gray',
        borderWidth: 1,
        justifyContent: "center",
        alignItems: "center"
      }}>
        <View>
          <Text>phone number
          </Text>
        </View>
        <View>
          <TextInput
            keyboardType='phone-pad'
            onChangeText={(text) => this.setState({text})}
            value={this.state.text}
            placeholder={"phone number"}/>
        </View>
      </View>
    </TouchableWithoutFeedback>
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <View
        style={{
        width: 200,
        height: 60,
        marginTop: 25,
        borderColor: 'gray',
        borderWidth: 1,
        justifyContent: "center",
        alignItems: "center"
      }}>
        <View>
          <Text>password</Text>
        </View>
        <View>
          <TextInput
            keyboardType='phone-pad'
            secureTextEntry
            onChangeText={(password) => this.setState({password})}
            value={this.state.password}
            placeholder={"password"}/>
        </View>
      </View>
    </TouchableWithoutFeedback>
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <View
        style={{
        width: 200,
        height: 60,
        marginTop: 25,
        borderColor: 'gray',
        borderWidth: 1,
        justifyContent: "center",
        alignItems: "center"
      }}>

        <Text>password2</Text>
        <TextInput
          keyboardType='phone-pad'
          secureTextEntry
          onChangeText={(password2) => this.setState({password2})}
          value={this.state.password2}
          placeholder={"password2"}/>
      </View>
    </TouchableWithoutFeedback>
    <Button
      title="getcode"
      onPress={() => this.getCode(this.state.text, this.state.password)}/>
  </View>
);
 }
}  

SecondPage.js

export default class SecondPage extends React.Component {
input = React.createRef();
constructor(props) {
super(props);

this.state = {
  value: "",
  focused: false,
  uuid: this.props.navigation.state.params.uuid,
  };
 }

 state = {
  codeConf: '',

 }

   sendCode(uid, code) {
   const body = new FormData
   body.append("authentication", uid)
   body.append("code", code)
   fetch('url', {
    method: 'POST',
    body,
    headers: {
      Token: "2f30743e-014d-4f0f-8707-73ae550d8f14"
    }
  }).then(function (response) {
    console.log(uid + "code is " + code)
    console.log(response);
    if (response.ok) {
      this.props.navigation.navigate('ThirdPage');
    } else {
      console.log(response.status)
    }
  })
  .catch((error) => {
    console.error(error);
  });
  }

 render() {
return (
  <View
    style={{
    flex: 1,
    backgroundColor: '#FDD7E4',
    alignSelf: 'stretch',
    textAlign: 'center',
    borderWidth: 1,
    justifyContent: "center",
    alignItems: "center"
  }}>

    <CodeInput
      ref="codeInputRef2"
      secureTextEntry
      codeLength={6}
      keyboardType='phone-pad'
      activeColor='rgba(0, 0, 0, 1)'
      inactiveColor='rgba(0, 0, 0 , 0.1)'
      autoFocus={true}
      ignoreCase={true}
      inputPosition='center'
      size={50}
      onFulfill={(code) => {
      this.setState({codeConf: code})
    }}/>
    <Button
      title="send code"
      onPress={this.sendCode(this.state.uuid, this.state.codeConf)} />
  </View>
)
  }
}

ThirdPage.js

export default class ThirdPage extends React.Component {
 render() {
return (

  <View style={styles}>
    <Text>
      Hi there
    </Text>
  </View>
)
 }
}

And finally App.js

class App extends React.Component {
  render() {
  return (<AppStackNavigator />)
 }
}

 const AppStackNavigator = createStackNavigator({
 FirstPage: {
  screen: FirstPage
 },
 SecondPage: {
  screen: SecondPage
  },
 ThirdPage: {
   screen: ThirdPage
  }
  }, {initialRouteName: 'FirstPage'})

   export default createAppContainer(AppStackNavigator);

I don't really why it happens, because react-navigation says that all then screens from App.js is sent to every screen as this.props.navigation, so I can access them from anywhere.

The issue is because you have lost scope by not binding your functions, this means that you are no longer accessing the correct value of this . You can fix this issue by using arrow functions.

Rewrite your sendCode function in the following way, noticing the use of arrow functions

sendCode = (uid, code) => {    // <- arrow function
  const body = new FormData();
  body.append('authentication', uid);
  body.append('code', code);
  fetch('url', {
    method: 'POST',
    body,
    headers: {
      Token: '2f30743e-014d-4f0f-8707-73ae550d8f14'
    }
  }).then(response => { // <- arrow function
    console.log(uid + 'code is ' + code);
    console.log(response);
    if (response.ok) {
      this.props.navigation.navigate('ThirdPage');
    } else {
      console.log(response.status);
    }
  }).catch((error) => {
    console.error(error);
  });
}

And finally update the code in your button to be.

<Button
  title="send code"
  onPress={() => this.sendCode(this.state.uuid, this.state.codeConf)} />

you need to bind and pass function definition to onPress prop of Button component in SecondPage.js.

<Button
  title="send code"
  onPress={()=>this.sendCode(this.state.uuid,this.state.codeConf)} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM