如何在React组件中处理异步请求的副作用

时间:2018-10-12 08:07:18

标签: reactjs react-native

我有一个使用mobx的异步api调用,该调用根据服务器响应设置成功或失败道具。如果成功,我必须导航到其他屏幕/路线,否则显示错误。

我可以显示错误消息,没有任何问题。但是,当尝试在渲染功能中导航或推入不同的路线时,我收到此警告

Warning: Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

哪个组件生命周期功能最适合我的情况?

 render() {
console.log(this.props);
const navigation = this.props.navigation;
const { sendOTPRequest } = this.props.store.userStore;
if (sendOTPRequest.state === "succeeded") {
  //if succeeded
  navigation.navigate("VerifyOTP");
  return null;
}
return (
  <View style={styles.container}>
    <View style={styles.formHeader}>
      <Image
        source={Logo}
        style={{
          height: 120,
          resizeMode: "contain",
          marginBottom: 5,
          display: "flex"
        }}
      />
      <Text style={styles.body}> Eat. Stamp. Reward.</Text>
    </View>
    <Formik
      initialValues={{
        phone: ""
      }}
      onSubmit={values => {
        this.sendOTP(values.phone);
      }}
      validate={values => {
        let errors = {};

        if (values.phone.length < 1) {
          errors.phone = "Invalid phone number";
        }

        return errors;
      }}
    >
      {({
        handleChange,
        handleSubmit,
        setFieldTouched,
        values,
        errors,
        touched
      }) => (
        <View style={styles.formBody}>
          <Text style={styles.headline}>Get authenticate your account</Text>
          <FormInput
            onChange={handleChange("phone")}
            value={values.phone}
            placeholder="Enter your phone number"
            keyboardType="phone-pad"
            onBlur={() => {
              setFieldTouched("phone");
            }}
          />
          <FormButton
            onClickHandler={handleSubmit}
            buttonText="Send OTP"
            isDisabled={
              values.phone.length < 1 ||
              sendOTPRequest.state === "requested"
            }
          />

          {touched.phone && errors.phone ? (
            <Text style={styles.body}> {errors.phone} </Text>
          ) : null}

          {sendOTPRequest.state === "failed" ? (
            <Text style={styles.body}> {sendOTPRequest.error_code} </Text>
          ) : null}
        </View>
      )}
    </Formik>
    <View style={styles.formFooter}>
      <View style={styles.indicatorContainer}>
        <View style={styles.indicator} />
        <View style={styles.indicatorActive} />
      </View>
    </View>
  </View>
);

}

1 个答案:

答案 0 :(得分:1)

尝试从渲染功能中删除导航代码,然后将其添加到componentWillReceiveProps(nextProps)中。检查以下代码

   componentWillReceiveProps(nextProps) {
const navigation = this.props.navigation;
const { sendOTPRequest } = this.nextProps.store.userStore;
if (sendOTPRequest.state === "succeeded") {
  //if succeeded
  navigation.navigate("VerifyOTP");
} 
}

您的渲染方法将是

render() {
console.log(this.props);
const navigation = this.props.navigation;
const { sendOTPRequest } = this.props.store.userStore;
if (sendOTPRequest.state === "succeeded") {
  return null;
}
return (
  <View style={styles.container}>
    <View style={styles.formHeader}>
      <Image
        source={Logo}
        style={{
          height: 120,
          resizeMode: "contain",
          marginBottom: 5,
          display: "flex"
        }}
      />
      <Text style={styles.body}> Eat. Stamp. Reward.</Text>
    </View>
    <Formik
      initialValues={{
        phone: ""
      }}
      onSubmit={values => {
        this.sendOTP(values.phone);
      }}
      validate={values => {
        let errors = {};

        if (values.phone.length < 1) {
          errors.phone = "Invalid phone number";
        }

        return errors;
      }}
    >
      {({
        handleChange,
        handleSubmit,
        setFieldTouched,
        values,
        errors,
        touched
      }) => (
        <View style={styles.formBody}>
          <Text style={styles.headline}>Get authenticate your account</Text>
          <FormInput
            onChange={handleChange("phone")}
            value={values.phone}
            placeholder="Enter your phone number"
            keyboardType="phone-pad"
            onBlur={() => {
              setFieldTouched("phone");
            }}
          />
          <FormButton
            onClickHandler={handleSubmit}
            buttonText="Send OTP"
            isDisabled={
              values.phone.length < 1 ||
              sendOTPRequest.state === "requested"
            }
          />

          {touched.phone && errors.phone ? (
            <Text style={styles.body}> {errors.phone} </Text>
          ) : null}

          {sendOTPRequest.state === "failed" ? (
            <Text style={styles.body}> {sendOTPRequest.error_code} </Text>
          ) : null}
        </View>
      )}
    </Formik>
    <View style={styles.formFooter}>
      <View style={styles.indicatorContainer}>
        <View style={styles.indicator} />
        <View style={styles.indicatorActive} />
      </View>
    </View>
  </View>
);
}