Subscribe on changes!

onBeforeUnmount not invoked for specific dynamicChildren-optimized case

avatar
Oct 20th 2020

Version

3.0.1

Reproduction link

https://codepen.io/basvanmeurs/pen/xxVoYVE?editors=1111

Steps to reproduce

Just run and view the console log

What is expected?

"MyTest umounted" is shown once

What is actually happening?

"MyTest umounted" is not shown


This behavior changed from 3.0.0 to 3.0.1. Probably related to https://github.com/vuejs/vue-next/commit/376883d1cfea6ed92807cce1f1209f943a04b625

avatar
Oct 20th 2020

In your repro block.id is always undefined since block is an array. What I found is an error when using:

const MyTest = {
  template: "#my-test",
  setup() {
    Vue.onBeforeUnmount(() => {
      console.log("MyTest umounted")
    });
  }
}  

const App = { 
  components: {
    MyTest
  },
  setup() {
    const block = Vue.shallowRef({id:1});
    setTimeout(() => {
      console.log("this should unmount")
      block.value = null;
    }, 1000);
    return {
      block
    }
  }
}

Vue.createApp(App).mount("#main");

maybe that's what you meant

avatar
Oct 20th 2020

the component was not unmounted at all

<my-test v-for="id in [block.id]" :key="id" /> => <my-test v-for="b in block" :key="b.id" />

avatar
Oct 20th 2020

Excuse me. I've updated the example

avatar
Apr 18th 2023

I think I've run into this same bug on Vue 3.2.47. I have one particular component which has two children, a slot, and a dialog, like:

<template>
  <slot :on-click="onClick"></slot>
  <Dialog {some options} />
</template>

In my <script setup>, I have an onBeforeUnmount and onUnmounted callback. Neither of them ever fires, in any circumstances. Just for this one component. And it's definitely being unmounted. Of note is that the Dialog only mounts content via <Teleport>

I've been trying to create a reproduction on CodeSandbox and I haven't been able to do it. Is there any way to prevent this "optimized" path from taking place?