卸载组件后如何存在功能

时间:2017-07-18 09:40:50

标签: javascript reactjs

我的怀疑与在反应组件中使用计时器有关,根据我的理解一旦组件卸载,之后其所有属性/方法将不存在。

根据DOC

  

componentWillUnmount()在组件出现之前立即被调用   未安装和销毁。 在此方法中执行任何必要的清理,   例如使计时器无效,取消网络请求或清除   up在componentDidMount中创建的任何DOM元素。

检查此代码段:



class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      3000
    );
  }

  componentWillUnmount() {
    //clearInterval(this.timerID);
  }

  tick() {
     console.log('called', this.props.no);
  }

  render() {
    return (
      <div>
        <h1>Clock {this.props.no}</h1>
      </div>
    );
  }
}

class App extends React.Component {
  
  constructor(){
     super();
     this.state = {unMount: false}
  }
  
  click(){
     console.log('unmounted successfully');
     this.setState({unMount: !this.state.unMount})
  }
  
  render(){
    return (
       <div>
          <button onClick={() => this.click()}>Unmount first</button>
           {!this.state.unMount && <Clock no={1}/>}
           <Clock no={2}/>
       </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='root'/>
&#13;
&#13;
&#13;

这里我正在渲染两个时钟组件并卸载第一个成功发生按钮的按钮,它也会更新DOM,即使在卸载第一个组件计时器后正在通过{{1正确打印道具值}}

我没有在console.log()中清除计时器

componentWillUmount

我怀疑是:

componentWillUnmount() {
    //clearInterval(this.timerID);
}

我在计时器中传递类方法作为回调,因此一旦卸载了组件,如何存在tick函数,此计时器如何解析this.timerID = setInterval( () => this.tick(), 3000 ); tick() { console.log('called', this.props.no); } 关键字和this函数组件卸载后? tick如何获得正确的价值?为什么它没有抛出错误:

  

无法读取未定义的刻度或未定义刻度

如何维护对这些功能的引用?

请帮助我在这里缺少的内容,请提供任何参考或示例。

3 个答案:

答案 0 :(得分:4)

与C ++不同,您无法在JavaScript中显式删除内存中的对象(也称为“destroy”)。您只能删除对它们的引用。一旦没有更多引用指向对象或其属性,它就有资格进行垃圾回收。只有这样,垃圾收集器才真正摧毁它。

Memory Management — JavaScript

在这种情况下,即使在卸载后,您仍然可以在闭包中对对象及其属性进行有效引用(this.tickthis.props等)。在某些时候,执行后,它们将超出范围,然后您的组件将被销毁,内存将被释放。

答案 1 :(得分:1)

大量深入研究React代码,我发现以下 doc

以及来自react github页面的代码

function unmountComponentFromNode(instance, container) {
  if (__DEV__) {
    ReactInstrumentation.debugTool.onBeginFlush();
  }
  ReactReconciler.unmountComponent(
    instance,
    false /* safely */,
    false /* skipLifecycle */,
  );
  if (__DEV__) {
    ReactInstrumentation.debugTool.onEndFlush();
  }

  if (container.nodeType === DOCUMENT_NODE) {
    container = container.documentElement;
  }

  // http://jsperf.com/emptying-a-node
  while (container.lastChild) {
    container.removeChild(container.lastChild);
  }
}

这表明React将从UI中删除组件并为垃圾收集做好准备,但即使删除了DOM元素, 类实例不是那么方法,道具仍然存在,因此继续执行setInterval。

仅当不再使用对this.ticks()this.props的引用时,它们才有资格进行垃圾回收

  

当事物(对象,字符串等)分配JavaScript值   创建并在不再使用时“自动”释放。   后一个过程称为垃圾收集。

答案 2 :(得分:0)

这不在react的工作方式,更像是javascript。您应该在componentWillUnmount上清除间隔。它甚至在文档中说:

  

在此方法中执行任何必要的清理,例如无效   定时器

您的代码已注释掉了吗?这不是问题吗?

  componentWillUnmount() {
    //clearInterval(this.timerID);
  }