【问题标题】:Can't call setState (or forceUpdate) on an unmounted component. React无法在未安装的组件上调用 setState(或 forceUpdate)。反应
【发布时间】:2018-09-08 13:20:07
【问题描述】:

Gutentag,伙计们!

卸载组件后,我的应用程序不断收到此错误消息:

Warning: Can't call setState (or forceUpdate) 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.
    in Header (at index.js:27)

现在这里是来自 Header 组件的代码:

class Header extends Component {
  isCancelled = false;
  state = {
    someStateVars: x,
    separateColumns: 'true',
  }

  handleChange = (event) => {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    if (!this.isCancelled) {
      this.setState({ //######THIS IS LINE 27######
        [name]: value
      });
    }
  }

  handleDisplayChange = (event) => {
    const value = event.target.value;
    const name = 'separateColumns';

    if (!this.isCancelled) {
      this.setState({  
        [name]: value
      }, () => {
        this.props.displayChange();
      });
    }
  }

  serversRefresh = () => {

    if (!this.isCancelled) {
      setTimeout(() => {
        this.setState({refreshed: false});
      }, localStorage.getItem('seconds')*1000); //disable refresh for 15 seconds
    }
  }

  reactivateButton = () => {
    if (!this.isCancelled) this.setState({refreshed: false});
  }

  componentDidMount() {
    if(localStorage.getItem('seconds')>5 && !this.isCancelled){
      this.setState({refreshed: true});
    }
  }

  componentWillUnmount() {
    this.isCancelled = true;
  }
}

当我看到我收到此错误时,我添加了 isCancelled 变量,该变量在 componentWillUnmount() 函数中更改为 true。

卸载 Header 组件后,15 秒后,当重新激活 serversRefreshbutton 时,我收到此错误消息。

我该如何解决?

在我遇到此问题的另一个组件上,“isCancelled”var 确实有帮助,但在这里我看到它没有影响并且问题仍然存在。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    只需将您的超时存储在一个变量中,例如

    this.timeout = setTimeout(/* your actions here*/, /* your timeout */)
    

    然后在componentWillUnmount中清除您的超时

    componentWillUnmount() {
        clearTimeout(this.timeout)
    }
    

    它应该可以解决您的问题,而无需像 this.isCancelled 这样的拐杖。检测组件的挂载状态是无操作的,因为即使卸载后它仍然从内存中卸载。

    setTimeout 返回计时器的 id,以后可以用它取消。 clearTimeout 通过它的 id 取消超时,如果它还没有执行。

    您可以在此处阅读有关您的案例的更多信息:Why isMounted is antipattern

    MDN 上有关计时器的更多信息。

    【讨论】:

    • 我的 componentWillUnmount 中有一个 clearInterval,但我仍然收到此错误
    猜你喜欢
    • 2019-01-07
    • 2023-04-08
    • 2018-10-28
    • 2018-11-03
    • 2019-03-10
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多