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
.
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
.
Even though you called this.el.remove()
, you should still call the unmountComponentAtNode(this.el)
because unmountComponentAtNode
will clean up its event handlers and state, but the remove
method will not.
For example, Eventhough you have clicked to remove the div, you can still call it's click event handlers:
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With