我在componentdidmount中调用了ajax。然后在ajax promise中使用setState。
代码就像这样
fitcnb
当我导航到其他路线时,这会导致错误'无法在未安装的组件上设置'。
所以我认为我应该做的是删除componentwillunmount中的axios listener。你会怎么做?
答案 0 :(得分:7)
一个非常简单的解决方案可能是在卸载时设置一个标志,并在promise解析中使用它,如下所示:
componentDidMount(){
axios.post('mydomian.com/item/',this.state)
.then(function (response) {
if (this.unmounted) return;
const res = response.data
if (res.status === 'OK') {
this.setState({items :res.list})
}else{
console.log('can not load data', response)
}
}.bind(this))
}
componentWillUnmount(){
this.unmounted = true;
}
答案 1 :(得分:1)
我找到了一个由istarkov定义的优秀解决方案
const makeCancelable = (promise) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then((val) =>
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
);
promise.catch((error) =>
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
},
};
};
使用方法:
const somePromise = new Promise(r => setTimeout(r, 1000));
const cancelable = makeCancelable(somePromise);
cancelable
.promise
.then(() => console.log('resolved'))
.catch(({isCanceled, ...error}) => console.log('isCanceled', isCanceled));
// Cancel promise
cancelable.cancel();
已找到解决方案there。
我的实施。
在我的职能范围内
const promiseShareByEmail = makeCancelable(this.props.requestShareByEmail(obj.email, obj.url));
promiseShareByEmail.promise.then(response => {
const res = response.data;
if (res.code != 0)
throw new Error(res.message);
this.setState({
message: {
text: TextMeasurements.en.common.success_share_test,
code: Constants.ALERT_CODE_SUCCESS
}
});
}).catch(err => {
if (err.isCanceled)
return;
this.setState({
message: {
text: err.message,
code: Constants.ALERT_CODE_ERROR
}
})
});
this.promiseShareByEmail = promiseShareByEmail;
this.props.requestShareByEmail(obj.email, obj.url)
该函数从axios返回promise。
当组件将卸载时,应该调用cancel函数。
componentWillUnmount() {
this.promiseShareByEmail.cancel();
}
享受。