如果删除了组件的容器,是否需要调用`unmountComponentAtNode`?

时间:2017-09-29 00:56:55

标签: reactjs react-dom

我在名为SettingsTab的包装器中呈现React组件TeamView。它的API看起来像

class TeamView {
  constructor() {
    this.el = document.createElement('div');
  }

  render() {
    ReactDOM.render(<SettingsTab/>, this.el);
    return this;
  }

  remove() {
    this.el.remove(); 
  }
}

使用像

这样的东西
// to present the team view
const teamView = new TeamView();
document.body.appendChild(teamView.render().el);

// to remove the team view
teamView.remove();

我想知道的是,应该TeamView#remove在致电ReactDOM. unmountComponentAtNode(this.el) 之前致电this.el.remove()

我可以在网络上找到的示例看起来只有unmountComponentAtNode才需要调用,如果容器将保留在DOM中;并且新的portals example只是删除了容器,而没有调用unmountComponentAtNode

但是,我不确定这是否特别,因为它正在使用门户网站,this post使得调用unmountComponentAtNode似乎总是好的做法。

3 个答案:

答案 0 :(得分:10)

是的,调用unmountComponentAtNode()很重要,因为如果你不这样做,树下面的任何组件都不会知道它们已被卸载。

用户定义的组件通常在componentDidMount中执行某些操作,从而在全局环境中创建对树的引用。例如,您可以添加window事件处理程序(不受React管理),Redux商店订阅,setInterval调用等。所有这些都很好并且正常,只要这些绑定在componentWillUnmount中删除。

但是,如果您只是从DOM中删除根但从不调用unmountComponentAtNode,则React将不知道该树中的组件是否需要卸载。由于他们的componentWillUnmount永远不会触发,所以这些订阅会保留,并阻止整棵树被垃圾收集。

因此,出于所有实际目的,如果要删除该容器节点,则应始终卸载root。否则你很可能会得到一个内存泄漏 - 如果不是现在,那么稍后当你的一些组件(可能在树的深处,甚至可能来自第三方库)在他们的componentDidMount中添加订阅时。

答案 1 :(得分:1)

即使您拨打了this.el.remove(),仍然应该调用unmountComponentAtNode(this.el),因为unmountComponentAtNode会清除其事件处理程序和状态,但remove方法不会。 / p>

例如,尽管你已经点击删除了div,但仍然可以调用它的click事件处理程序:

var tap = document.querySelector('.tap');
var other = document.querySelector('.other');
tap.addEventListener('click', function(e) {
  console.log(tap.getAttribute('data-name') + ' has been clicked');
  tap.remove();
});

other.addEventListener('click', function(e) {
  tap.click();
});
<div class="tap" data-name="tap">First Click me to remove me</div>
<div class="other">Then Click me </div>

答案 2 :(得分:0)

我在#react-internals Discord频道中提出了这个问题并收到了以下回复:

answer to question

所以,这与@jiangangxiong上面所说的一致:只要我们

  • 不要保留我们自己对组件DOM元素的引用
  • 也不在React
  • 之外附加事件处理程序
  • 并且只需要支持现代浏览器

我们只需要remove容器就可以收集组件的事件处理程序和状态垃圾,而不需要调用unmountComponentAtNode