问题是我收到此警告:
警告:无法在已卸载的组件上调用setState(或forceUpdate)。这是空操作,但它表明应用程序中发生内存泄漏。要修复此问题,请取消componentWillUnmount方法中的所有订阅和异步任务。
原因是这样的:
componentDidUpdate(props, state) {
const {
pushNotificationData,
unassignedPickUpPassengers,
unassignedDropOffPassengers,
} = this.props;
if (props.pushNotificationData !== pushNotificationData) {
this.applyOpacityForSomeSeconds(0.5, 0);
}
if (
props.unassignedPickUpPassengers !== unassignedPickUpPassengers ||
props.unassignedDropOffPassengers !== unassignedDropOffPassengers
) {
this.applyOpacityForSomeSeconds(1, 1000);
}
}
applyOpacityForSomeSeconds = (setOpacity, timeout) =>
setTimeout(() => {
this.setState({ lastIndexOpacity: setOpacity });
}, timeout);
如何清除componentWillUnmount的超时?是这样做的正确方法还是其他方法?
答案 0 :(得分:2)
您需要保留它的引用,例如:
applyOpacityForSomeSeconds = (setOpacity, timeout) =>
clearTimeout(this.timeout) // notice that you don't have to check if this.timeout is null or undefined just let clearTimeout handle it
this.timeout = setTimeout(() => {
this.setState({ lastIndexOpacity: setOpacity });
}, timeout);
注意,该引用设置为this.timeout = setTimeout(...
。您可以在构造函数中或其他地方使用null
初始化引用-我总是在犹豫。 :)
如果需要,可以将clearTimeout(this.timeout)
移动或复制到componentWillUnmount
中。
答案 1 :(得分:1)
一个简单的解决方案:
componentWillUnmount() {
this.isUnmounted = true;
}
然后您可以将其添加到超时回调中:
setTimeout(() => {
if (!this.isUnmounted) {
this.setState({ lastIndexOpacity: setOpacity });
}
}, timeout);
如果卸载了组件,这将阻止setState
运行。
答案 2 :(得分:0)
setTimeout
返回可以与cancelTimeout
一起使用的句柄。您也可以将该句柄放到您的状态:
applyOpacityForSomeSeconds = (setOpacity, timeout) => {
this.setState({
opacityTimeout: setTimeout(() => {
this.setState({
lastIndexOpacity: setOpacity,
opacityTimeout: null
});
}, timeout);
});
}
componentWillUnmount() {
if (this.state.opacityTimeout) {
clearTimeout(this.state.opacityTimeout);
}
}
由于您有1秒钟的超时,因此可能有可能同时运行多个超时,具体取决于您的应用程序为此组件更新道具的速度。在这种情况下,最好使用句柄数组:
(假设您的初始状态会将opacityTimeouts
初始化为一个空数组)
applyOpacityForSomeSeconds = (setOpacity, timeout) => {
const handle = setTimeout(() => {
this.setState({
lastIndexOpacity: setOpacity,
opacityTimeouts: this.state.opacityTimeouts.filter(
h => h !== handle
)
});
}, timeout);
this.setState({
opacityTimeouts: [
...this.state.opacityTimeouts,
handle
]
});
}
componentWillUnmount() {
this.state.opacityTimeouts.forEach(handle => clearTimeout(handle));
}