onBeforeMount and onMount called, but onBeforeUnmount and onUnmount not, if inside <transition>
Vue version
3.2.27
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-5pepm1?file=src/components/Page1.vue
Steps to reproduce
If component A is itself loading a child component inside a <transition>
, but A is replaced by B during loading, the child component is only executing the onBeforeMount and onMount hook, but not the Unmount hooks, even though it is removed from the DOM and not visible anymore.
This issue only happens if the timing is right. In our project (with vue cli and a lot of stuff) I could reproduce it with a promise of 10ms, and a page transition after 100ms. But in the reproduction link it behaved differently. There it only executes the onBeforeMount and not the onMount, and I see an error which I don't get locally in our project.
What is expected?
onBeforeUnmount and onUnmounted should be called consistently and reliably!
What is actually happening?
Sometimes only the onBeforeMount and onMounted hooks are executed, and not the unmount hooks, even though the component gets destroyed by routing to a different page.
System Info
Windows 10, latest Chrome
Any additional comments?
No response
The thing is, in our project this inner component uses Teleport. Sometimes the backend sends an error and vue router redirects to the error page - this redirect happens while the Transition is running, and the inner component is mounted but never removed. So all states are still active, including the Teleport content. So I can't even work around this issue by resetting the state, since the Teleport is still showing content which doesn't belong there, as the current route is already a different one and it should have been removed.
Seems like the following edge-case causes troubles:
- Component is loaded inside "leave-transition" which is transitioning away from it (so it is removing the component after transition)
- inner component executes onBeforeMount and onMounted hooks
- inner component is technically removed, but still existing since it was detached from the DOM inside a transition
- component is still loaded and active. onUnmount is never called and component is never destroyed, even though it is not attached to the DOM anymore and should have been removed
- any teleport content within the inner component is still visible