React - 内存泄漏,ComponentWillUnmount / Axios 问题
React - Memory Leak, issues with ComponentWillUnmount / Axios
我正在执行一个从 componentDidMount 开始的 API 调用,但是当用户加载新组件时,会出现潜在内存泄漏的通知,请参阅下面的消息。我已经研究了不同的解决方案,但还没有发现任何有效的方法,我想知道是否可以使用 componentWillUnmount 在这个特定组件中解决这个问题,或者在 axios 调用本身中是否可以更好地处理它。
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
componentDidMount() {
this.loadBackground();
this.getUpdatedWeather();
this.getNewMartianPhotos();
}
checkMartianPhotos = () => {
if (this.state.martianMotion) {
console.log('still shooting');
this.getNewMartianPhotos();
} else {
return console.log('done now');
}
};
getNewMartianPhotos = () => {
let loadedImage = '';
let loadedInfo = '';
let loadedMeta = '';
let totalImage;
API.getMarsPhotos().then(data => {
// console.log(data.data);
// console.log(
// data.data.collection.items[this.state.martianCount].data[0].photographer
// );
// console.log(
// data.data.collection.items[this.state.martianCount].data[0].description
// );
// console.log(
// data.data.collection.items[this.state.martianCount].links[0].href
// );
totalImage = data.data.collection.items.length;
loadedImage =
data.data.collection.items[this.state.martianCount].links[0].href;
loadedInfo =
data.data.collection.items[this.state.martianCount].data[0].description;
loadedMeta =
data.data.collection.items[this.state.martianCount].data[0]
.photographer;
this.setState({
martianImage: loadedImage,
martianDescription: loadedInfo,
martianMeta: loadedMeta,
martianCount: this.state.martianCount + 1
});
if (this.state.martianCount < totalImage) {
console.log(
`shooting off, image count now ${this.state.martianCount} against ${totalImage}`
);
setTimeout(this.checkMartianPhotos, 10000);
}
});
};
componentWillUnmount() {
clearTimeout(this.checkMartianPhotos);
}
-------------------------------------
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
getMarsPhotos: () =>
axios
.get('https://images-api.nasa.gov/search?q=martian', {
cancelToken: source.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('request canceled', thrown.message);
} else {
console.log('there is an error that needs to be handled');
}
})
如错误所示,您的组件在卸载后调用 setState。这是因为您错误地清除了超时。您应该执行以下操作以正确清除卸载超时。
this.id = setTimeout(this.checkMartianPhotos, 10000);
然后用
清除
clearTimeout(this.id)
在componentWillUnmount
此外,尝试将异步逻辑(api 调用)移出组件。
请参阅 了解如何在 API 调用卸载组件后停止设置状态。
我正在执行一个从 componentDidMount 开始的 API 调用,但是当用户加载新组件时,会出现潜在内存泄漏的通知,请参阅下面的消息。我已经研究了不同的解决方案,但还没有发现任何有效的方法,我想知道是否可以使用 componentWillUnmount 在这个特定组件中解决这个问题,或者在 axios 调用本身中是否可以更好地处理它。
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
componentDidMount() {
this.loadBackground();
this.getUpdatedWeather();
this.getNewMartianPhotos();
}
checkMartianPhotos = () => {
if (this.state.martianMotion) {
console.log('still shooting');
this.getNewMartianPhotos();
} else {
return console.log('done now');
}
};
getNewMartianPhotos = () => {
let loadedImage = '';
let loadedInfo = '';
let loadedMeta = '';
let totalImage;
API.getMarsPhotos().then(data => {
// console.log(data.data);
// console.log(
// data.data.collection.items[this.state.martianCount].data[0].photographer
// );
// console.log(
// data.data.collection.items[this.state.martianCount].data[0].description
// );
// console.log(
// data.data.collection.items[this.state.martianCount].links[0].href
// );
totalImage = data.data.collection.items.length;
loadedImage =
data.data.collection.items[this.state.martianCount].links[0].href;
loadedInfo =
data.data.collection.items[this.state.martianCount].data[0].description;
loadedMeta =
data.data.collection.items[this.state.martianCount].data[0]
.photographer;
this.setState({
martianImage: loadedImage,
martianDescription: loadedInfo,
martianMeta: loadedMeta,
martianCount: this.state.martianCount + 1
});
if (this.state.martianCount < totalImage) {
console.log(
`shooting off, image count now ${this.state.martianCount} against ${totalImage}`
);
setTimeout(this.checkMartianPhotos, 10000);
}
});
};
componentWillUnmount() {
clearTimeout(this.checkMartianPhotos);
}
-------------------------------------
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
getMarsPhotos: () =>
axios
.get('https://images-api.nasa.gov/search?q=martian', {
cancelToken: source.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('request canceled', thrown.message);
} else {
console.log('there is an error that needs to be handled');
}
})
如错误所示,您的组件在卸载后调用 setState。这是因为您错误地清除了超时。您应该执行以下操作以正确清除卸载超时。
this.id = setTimeout(this.checkMartianPhotos, 10000);
然后用
清除clearTimeout(this.id)
在componentWillUnmount
此外,尝试将异步逻辑(api 调用)移出组件。
请参阅