简体   繁体   English

反应:是否可以通过将this.setState设置为空函数来防止卸载后的状态更新?

[英]React: Is it possible to prevent state update after unmount, via setting this.setState to empty function?

I am facing the problem that a network callback is trying to setState() of an unmounted component and receive the default console warning about this no-op. 我面临的问题是,网络回调正在尝试对已卸载组件的setState()进行设置,并收到有关此无操作的默认控制台警告。

It wasn't possible for me to track why the unmount happens but I found a solution suggesting to set the function to nothing in componentWillUnmount(). 我无法跟踪为什么会发生卸载,但是我找到了一个解决方案,建议在componentWillUnmount()中将函数设置为空。 It didn't work and I tested to set this.setState to nothing. 它没有用,我测试了将this.setState设置为空。 See below. 见下文。

The error disappears but I want to ask whether that is a valid solution. 错误消失了,但我想问一问这是否是有效的解决方案。 Here the code: 这里的代码:

  componentDidMount() {
    this.fetchLogItems(10, 'recentChanges');
  }

  componentWillUnmount() {
    this.setState = () => {};
  }

  fetchLogItems = (limit, stateRef) => {
    let tmpObj = {};
    base.fetch('_changelogs', {
      context: this,
      then(data) {
        tmpObj[stateRef] = {...data}
        tmpObj.loading = false;
        this.setState({...tmpObj})
      },
      catch(err){console.error(err)}
    });
  };

Two options: 两种选择:

  • be sure that whatever helpers that you are using also allow for the use of "destructors" (cancellations, and I definitely prefer the use of "cancellations") 确保您正在使用的任何帮助程序也允许使用“析构函数”(取消,我绝对更喜欢使用“取消”)
  • if not, then you may introduce a "flag" to your class 如果没有,那么您可以在课堂上引入一个“标志”

If your library allows for some "cancellation", "destruction", or "cleanup", then you may simply do: 如果您的库允许“取消”,“销毁”或“清理”,那么您可以简单地执行以下操作:

componentWillUnmount() {
  base.cancelFetch(); // or something similar.
}

Otherwise, you may be able to introduce a class property to your component. 否则,您可以向您的组件引入属性。 Perhaps name it isUnmounted . 也许将其命名为isUnmounted In componentWillUnmount , set this.isUmounted to true. componentWillUnmountthis.isUmounted设置为true。 Wrap the this.setState call in an if -statement that checks if isUnmounted is false, and if it is, then you may call this.setState . this.setState调用包装在if -statement中,该语句检查isUnmounted是否为false,如果为false,则可以调用this.setState This is actually a very common pattern. 这实际上是一种非常常见的模式。

It may " feel " ugly, but, by defacto, this pattern seems to be idiomatic among React developers. 它可以“ 感觉 ”丑,但是,通过事实上的,这种格局似乎阵营开发者惯用的。 If not, at least it is a pragmatic solution to problems similar to yours. 如果不是这样,至少对于与您类似的问题,这是一种务实的解决方案。

constructor() {
  // HERE
  this.isUmounted = false;
}

componentDidMount() {
  this.fetchLogItems(10, 'recentChanges');
}

componentWillUnmount() {
  // HERE
  this.isUmounted = true;
}

fetchLogItems = (limit, stateRef) => {
  let tmpObj = {};
  base.fetch('_changelogs', {
    context: this,
    then(data) {
      tmpObj[stateRef] = {...data}
      tmpObj.loading = false;
      // WRAP THE `this.setState` here.
      if (!this.isUnmounted) {
        this.setState({...tmpObj})
      }
    },
    catch(err){console.error(err)}
  });
};

However, I prefer the use of libraries and helpers that support cancellation. 但是,我更喜欢使用支持取消的库和助手。 It's definitely guarantees some level of cleanup. 绝对可以保证一定程度的清理。 Without cancellation, we risk introducing memory leaks. 如果不取消,我们就有引入内存泄漏的风险。

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

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