diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts
index d822a992816..6fec755106a 100644
--- a/packages/runtime-core/__tests__/components/Suspense.spec.ts
+++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts
@@ -1185,6 +1185,72 @@ describe('Suspense', () => {
expect(calls).toEqual([`one mounted`, `one unmounted`, `two mounted`])
})
+ test('mount the fallback content is in the correct position', async () => {
+ const makeComp = (name: string, delay = 0) =>
+ defineAsyncComponent(
+ {
+ setup() {
+ return () => h('div', [name])
+ }
+ },
+ delay
+ )
+
+ const One = makeComp('one')
+ const Two = makeComp('two', 20)
+
+ const view = shallowRef(One)
+
+ const Comp = {
+ setup() {
+ return () =>
+ h('div', [
+ h(
+ Suspense,
+ {
+ timeout: 10
+ },
+ {
+ default: h(view.value),
+ fallback: h('div', 'fallback')
+ }
+ ),
+ h('div', 'three')
+ ])
+ }
+ }
+
+ const root = nodeOps.createElement('div')
+ render(h(Comp), root)
+ expect(serializeInner(root)).toBe(
+ `
`
+ )
+
+ await deps[0]
+ await nextTick()
+ expect(serializeInner(root)).toBe(
+ ``
+ )
+
+ view.value = Two
+ await nextTick()
+ expect(serializeInner(root)).toBe(
+ ``
+ )
+
+ await new Promise(r => setTimeout(r, 10))
+ await nextTick()
+ expect(serializeInner(root)).toBe(
+ ``
+ )
+
+ await deps[1]
+ await nextTick()
+ expect(serializeInner(root)).toBe(
+ ``
+ )
+ })
+
// #2214
// Since suspense renders its own root like a component, it should not patch
// its content in optimized mode.
diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts
index 5e5521b09be..426ca0cd32c 100644
--- a/packages/runtime-core/src/components/Suspense.ts
+++ b/packages/runtime-core/src/components/Suspense.ts
@@ -582,6 +582,7 @@ function createSuspenseBoundary(
// invoke @fallback event
triggerEvent(vnode, 'onFallback')
+ const anchor = next(activeBranch!)
const mountFallback = () => {
if (!suspense.isInFallback) {
return
@@ -591,7 +592,7 @@ function createSuspenseBoundary(
null,
fallbackVNode,
container,
- next(activeBranch!),
+ anchor,
parentComponent,
null, // fallback tree will not have suspense context
isSVG,