Vue version
3.5.30
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-assboxgb
Steps to reproduce
Hi Vue team,
when toggling between two <template v-if> branches that each contain a <Transition mode="out-in"> wrapping a <Suspense> with an async-setup component, every toggle leaves the previous DOM subtree behind in the container.After N clicks you end up with N+1 copies of the async child rendered. Sibling nodes in the same Fragment (e.g. an <h4>) are removed correctly - only the Transition/Suspense subtree leaks.
I came across this from (as a Member) nuxt/nuxt#34859 - it surfaces there because renders exactly this structure internally. I reduced it to a Vue-only repro (no Nuxt, no vue-router), which is why I'm filing it here. Conditions (all required to reproduce):
- Conditional parent is a
<template v-if> Fragment - switching to <div v-if> makes it disappear
<Transition mode="out-in"> - removing mode makes it disappear
- A
<Suspense> inside the Transition
- A descendant component with async setup (so Suspense actually suspends)
What I observed while debugging: the component lifecycle looks clean - onUnmounted fires for every leaving instance. But the DOM subtree stays attached to the container anyway. This points at the out-in leave path interacting badly with suspensible Suspense: the afterLeave callback that should call hostRemove(el) never runs, because the surrounding itself is torn down before it gets a chance to fire.
What is expected?
Component should been removed from DOM.
What is actually happening?
Component is still staying with N copies.
System Info
Any additional comments?
No response
Vue version
3.5.30
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-assboxgb
Steps to reproduce
Hi Vue team,
when toggling between two
<template v-if>branches that each contain a<Transition mode="out-in">wrapping a<Suspense>with an async-setup component, every toggle leaves the previous DOM subtree behind in the container.After N clicks you end up with N+1 copies of the async child rendered. Sibling nodes in the same Fragment (e.g. an<h4>) are removed correctly - only the Transition/Suspense subtree leaks.I came across this from (as a Member) nuxt/nuxt#34859 - it surfaces there because renders exactly this structure internally. I reduced it to a Vue-only repro (no Nuxt, no vue-router), which is why I'm filing it here. Conditions (all required to reproduce):
<template v-if>Fragment - switching to<div v-if>makes it disappear<Transition mode="out-in">- removing mode makes it disappear<Suspense>inside the TransitionWhat I observed while debugging: the component lifecycle looks clean -
onUnmountedfires for every leaving instance. But the DOM subtree stays attached to the container anyway. This points at the out-in leave path interacting badly with suspensible Suspense: theafterLeavecallback that should callhostRemove(el)never runs, because the surrounding itself is torn down before it gets a chance to fire.What is expected?
Component should been removed from DOM.
What is actually happening?
Component is still staying with N copies.
System Info
Any additional comments?
No response