Is it necessary to call `unmountComponentAtNode` if the component's container is removed?

Jeffrey Wear picture Jeffrey Wear · Sep 29, 2017 · Viewed 10.2k times · Source

I render a React component SettingsTab within a wrapper called TeamView. Its API looks something like

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

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

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

used something like

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

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

And what I'm wondering is, should TeamView#remove call ReactDOM. unmountComponentAtNode(this.el) before calling this.el.remove()?

The examples I can find around the web make it seem like unmountComponentAtNode only needs to be called if the container is going to remain in the DOM; and the new portals example just removes the container, without calling unmountComponentAtNode.

But, I'm not sure if that's special because it's using a portal, and this post makes it kind of seem like it's always good practice to call unmountComponentAtNode.

Answer

Dan Abramov picture Dan Abramov · Jan 11, 2018

Yes, it is important to call unmountComponentAtNode() because if you don't do this, none of the components below in the tree will know they have been unmounted.

User-defined components often do something in componentDidMount that creates a reference to the tree from the global environment. For example, you may add a window event handler (which isn't managed by React), a Redux store subscription, a setInterval call, etc. All of this is fine and normal as long as these bindings are removed in componentWillUnmount.

However, if you just remove the root from the DOM but never call unmountComponentAtNode, React will have no idea the components in that tree need to be unmounted. Since their componentWillUnmount never fires, those subscriptions stay, and prevent the whole tree from getting garbage collected.

So for all practical purposes you should always unmount the root if you're going to remove that container node. Otherwise you'll most likely get a memory leak—if not now, then later when some of your components (potentially deep in the tree, maybe even from third-party libraries) add subscriptions in their componentDidMount.