Reputation: 25
At the moment, I am working on a simple application that orchestrates multiple webcomponents. One of these components holds a setInterval function. The function keeps running, even when the component itself is not present in the dom anymore. Can one explain to me why this is the case?
Here is a simple reproduction:
const selectorEl = document.getElementsByTagName('body')[0];
selectorEl.innerHTML = '<my-component></my-component>'; // Append custom component to body
class WebComponent extends HTMLElement {
constructor() {
super();
this.innerHTML = '<span>This should not be visible since I am removed instantly!</span>';
setInterval(() => console.log('I am still running...'), 2000);
}
}
window.customElements.define('my-component', WebComponent);
selectorEl.innerHTML = ''; // Remove element from the dom directly
Upvotes: 0
Views: 651
Reputation: 2764
You need to use lifecycle callbacks to correctly use setInterval
and clearInterval
.
Example below:
const selectorEl = document.getElementsByTagName("body")[0];
selectorEl.innerHTML = "<my-component></my-component>"; // Append custom component to body
class WebComponent extends HTMLElement {
connectedCallback() {
this.innerHTML =
"<span>This should not be visible since I am removed instantly!</span>";
this.interval = setInterval(
() => console.log("I am still running...", Math.random()),
2000
);
}
disconnectedCallback() {
clearInterval(this.interval);
}
}
window.customElements.define("my-component", WebComponent);
setTimeout(() => selectorEl.innerHTML = "",7000); // Remove element from the dom directly
Upvotes: 2
Reputation: 21173
A more concise example:
<script>
customElements.define("my-component", class extends HTMLElement {
connectedCallback() {
console.log("connectedCallback" , this.isConnected);
this.innerHTML = "A Web Component";
setTimeout(() => this.remove(), 2000); // triggers disconnectedCallback
this.interval = setInterval(() => this.innerHTML += ".", 50);
}
disconnectedCallback() {
console.log("disconnectedCallback" , this.isConnected);
clearInterval(this.interval);
}
});
</script>
<my-component></my-component>
Notes
The DOM element no longer exists in the disconnectedCallback
, but the Web Component stills exists in memory, so you can access anything that was created(or attached) prior
Drag/drop or append
operations trigger the disconnectedVCallback
and then the connectedCallback
again
Upvotes: 0
Reputation: 18036
Web Components have their own lifecycle and when an element is deleted from the DOM disconnectedCallback()
get's called. is lifecycle hook is called when the element is removed from the DOM. hence, it’s an ideal place to add cleanup logic and to free up resources. in your case, call the clearInterval
method which clears a timer set with the setInterval() method like you did.
disconnectedCallback() {
clearInterval(interval)
}
Upvotes: 0
Reputation: 648
You need to use disconnectedCallback hook it will get called once the component will get removed from the dom, so in this function, you can clear your interval.
disconnectedCallback() {
clearInterval(interval)
}
Upvotes: 0