未定义不是对象(评估“ this.props.navigation”)

时间:2019-02-28 19:24:03

标签: javascript reactjs react-native

我的导航突然中断了。因此,共有3个屏幕/组件,我正在使用react-navigation在它们之间进行导航。 第一个屏幕是输入手机号码和密码,它被发送到api,一些数据被保存到状态并传递到第二个屏幕,我在此输入代码短信并向api发送另一个请求,如果response.status == 200,它将转到第三屏幕。从第一屏导航到第二屏有效,但从第二屏导航到第三屏无效。当我转到第三屏时发生错误。

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>
)
 }
}

最后是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);

我真的不知道为什么会发生这种情况,因为react-navigation表示来自App.js的所有屏幕都作为this.props.navigation发送到每个屏幕,因此我可以从任何地方访问它们。

2 个答案:

答案 0 :(得分:1)

问题是因为您没有绑定功能而失去了范围,这意味着您不再访问this的正确值。您可以使用箭头功能解决此问题。

通过以下方式重写sendCode函数,注意使用箭头函数

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);
  });
}

最后将按钮中的代码更新为。

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

答案 1 :(得分:0)

您需要将函数定义绑定并传递到SecondPage.js中Button组件的onPress属性。

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