onDestroy not working when component target is removed

Viewed 291

I'm having a problem where onDestroy is not called inside a Svelte component when the component's parent HTML element is removed. How can I fix this? I'm creating my element like this, in order to properly interface with another JS lib (TipTap/ProseMirror).

Example: https://svelte.dev/repl/4e1ef2e35fce432b9ba63f87db0c95cb

App.svelte

<script>
    import Nested from "./Nested.svelte";
    import { onMount } from 'svelte';
    
    let target;
    
    onMount(() => {
        const root = document.getElementById("root");
        target = document.createElement("div");
        new Nested({ target });
        root.appendChild(target);
    });
</script>

<div id="root"></div>
<button on:click={() => target.remove()}>Remove</button>

Nested.svelte

<script>
    import { onMount, onDestroy } from 'svelte';
    
    onMount(() => console.log("mount")); // Run
    onDestroy(() => console.log("destroy")); // Not run
</script>

<h1>Nested Component</h1>
1 Answers

If you create the component by hand, you also need to destroy it by hand. You need to call $destroy on its instance before removing the Dom element:

<script>
    import Nested from "./Nested.svelte";
    import { onMount } from 'svelte';
    
    let target;
    let nested;
    
    onMount(() => {
        const root = document.getElementById("root");
        target = document.createElement("div");
        nested = new Nested({ target });
        root.appendChild(target);
    });
</script>

<div id="root"></div>
<button on:click={() => { nested.$destroy();  target.remove() }}>Remove</button>

Docs: https://svelte.dev/docs#$destroy

Related