When a component is replaced with another one, the DOM is updated, before the componentWillUnmount event is called. This prevents the execution of scripts, depending on the DOM Elements of the component.
I created an example. When you change from the Home tab to another one, you should get an alert, with the result of the shown query. Inside the console, I log the trace of the call.
Additionally the componentWillUnmount is iterated in a top-down approach, so if a child of a component has a componentWillUnmount set, it's fired, when the containing component is already removed, resulting in the same error.
This example already contains the fix for No. 1 and shows the problem of the nested component in the same way, as ex 1.
componentWillUnmount should be called, before the DOM Nodes are removed.
componentWillUnmount is called, after the DOM Nodes are removed.
In vdom/component.js the child is replaced and after that replacement, 'componentWillUnmount' is called.
In vdom/component.js the base node is removed and the the children are collected and removed.
Change vdom/component.js to
if (baseParent && base!==baseParent) {
baseParent.replaceChild(base, initialBase);
if (!toUnmount) {
initialBase._component = null;
recollectNodeTree(initialBase, false);
} else {
baseParent.insertBefore(initialBase,base);
unmountComponent(toUnmount);
toUnmount = null;
}
}
The traversal of the DOM tree should be bottom top, while calling componentWillUnmount. After reaching the top node, which has to be removed, it could be removed without removing each child separately.
The code from the linked snippet would make a great test case:
class Foo extends Component {
componentWillUnmount() {
expect(document.getElementById("foo")).to.not.equal(null);
};
render() {
return <div id="foo" />;
}
}
render(<Foo />, scratch);
render(null, scratch);
Most helpful comment
The code from the linked snippet would make a great test case: