diff --git a/packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts b/packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts
index 87dc922dd..e912af285 100644
--- a/packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts
+++ b/packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts
@@ -3,6 +3,7 @@ import { nextTick, resolveDynamicComponent } from '@vue/runtime-dom'
import {
createComponentWithFallback,
createDynamicComponent,
+ defineVaporComponent,
renderEffect,
setHtml,
setInsertionState,
@@ -79,4 +80,34 @@ describe('api: createDynamicComponent', () => {
mount()
expect(html()).toBe('
')
})
+
+ test('switch dynamic component children', async () => {
+ const CompA = defineVaporComponent({
+ setup() {
+ return template('A
')()
+ },
+ })
+ const CompB = defineVaporComponent({
+ setup() {
+ return template('B
')()
+ },
+ })
+
+ const current = shallowRef(CompA)
+ const { html } = define({
+ setup() {
+ const t1 = template('')
+ const n2 = t1() as any
+ setInsertionState(n2)
+ createDynamicComponent(() => current.value)
+ return n2
+ },
+ }).render()
+
+ expect(html()).toBe('')
+
+ current.value = CompB
+ await nextTick()
+ expect(html()).toBe('')
+ })
})
diff --git a/packages/runtime-vapor/src/apiCreateDynamicComponent.ts b/packages/runtime-vapor/src/apiCreateDynamicComponent.ts
index 2126611d7..945e0f38d 100644
--- a/packages/runtime-vapor/src/apiCreateDynamicComponent.ts
+++ b/packages/runtime-vapor/src/apiCreateDynamicComponent.ts
@@ -1,9 +1,15 @@
import { resolveDynamicComponent } from '@vue/runtime-dom'
-import { DynamicFragment, type VaporFragment } from './block'
+import { DynamicFragment, type VaporFragment, insert } from './block'
import { createComponentWithFallback } from './component'
import { renderEffect } from './renderEffect'
import type { RawProps } from './componentProps'
import type { RawSlots } from './componentSlots'
+import {
+ insertionAnchor,
+ insertionParent,
+ resetInsertionState,
+} from './insertionState'
+import { isHydrating, locateHydrationNode } from './dom/hydration'
export function createDynamicComponent(
getter: () => any,
@@ -11,9 +17,18 @@ export function createDynamicComponent(
rawSlots?: RawSlots | null,
isSingleRoot?: boolean,
): VaporFragment {
+ const _insertionParent = insertionParent
+ const _insertionAnchor = insertionAnchor
+ if (isHydrating) {
+ locateHydrationNode()
+ } else {
+ resetInsertionState()
+ }
+
const frag = __DEV__
? new DynamicFragment('dynamic-component')
: new DynamicFragment()
+
renderEffect(() => {
const value = getter()
frag.update(
@@ -27,5 +42,10 @@ export function createDynamicComponent(
value,
)
})
+
+ if (!isHydrating && _insertionParent) {
+ insert(frag, _insertionParent, _insertionAnchor)
+ }
+
return frag
}