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



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

我可以毫无问题地显示错误消息。但是,在渲染函数中尝试导航或推送到不同的路线时,我收到此警告

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

}

尝试从渲染函数中删除导航代码并将其添加到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>
);
}