繁体   English   中英

如何清除在组件生命周期中创建的setTimeout?

[英]How can I clear a setTimeout which is created on a component life cycle?

问题是我收到以下警告:

警告:无法在已卸载的组件上调用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的超时? 是这样做的正确方法还是其他方法?

您需要保留一个引用,例如:

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

一个简单的解决方案:

componentWillUnmount() {
  this.isUnmounted = true;
}

然后,您可以添加到超时回调中:

setTimeout(() => {
  if (!this.isUnmounted) {
    this.setState({ lastIndexOpacity: setOpacity });
  }
}, timeout);

如果卸载了组件,这将阻止setState运行。

setTimeout返回可以与cancelTimeout使用的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));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM