Skip to content

Commit aa0c13f

Browse files
committed
fix(Suspense): handle switching away from kept-alive component before resolve
close #6416 using test from #6467
1 parent 96aeb24 commit aa0c13f

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

packages/runtime-core/__tests__/components/Suspense.spec.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import {
1919
shallowRef,
2020
SuspenseProps,
2121
resolveDynamicComponent,
22-
Fragment
22+
Fragment,
23+
KeepAlive
2324
} from '@vue/runtime-test'
2425
import { createApp, defineComponent } from 'vue'
2526
import { type RawSlots } from 'packages/runtime-core/src/componentSlots'
@@ -1638,6 +1639,55 @@ describe('Suspense', () => {
16381639
expect(serializeInner(root)).toBe(expected)
16391640
})
16401641

1642+
// #6416
1643+
test('KeepAlive with Suspense', async () => {
1644+
const Async = defineAsyncComponent({
1645+
render() {
1646+
return h('div', 'async')
1647+
}
1648+
})
1649+
const Sync = {
1650+
render() {
1651+
return h('div', 'sync')
1652+
}
1653+
}
1654+
const components = [Async, Sync]
1655+
const viewRef = ref(0)
1656+
const root = nodeOps.createElement('div')
1657+
const App = {
1658+
render() {
1659+
return h(KeepAlive, null, {
1660+
default: () => {
1661+
return h(Suspense, null, {
1662+
default: h(components[viewRef.value]),
1663+
fallback: h('div', 'Loading-dynamic-components')
1664+
})
1665+
}
1666+
})
1667+
}
1668+
}
1669+
render(h(App), root)
1670+
expect(serializeInner(root)).toBe(`<div>Loading-dynamic-components</div>`)
1671+
1672+
viewRef.value = 1
1673+
await nextTick()
1674+
expect(serializeInner(root)).toBe(`<div>sync</div>`)
1675+
1676+
viewRef.value = 0
1677+
await nextTick()
1678+
1679+
expect(serializeInner(root)).toBe('<!---->')
1680+
1681+
await Promise.all(deps)
1682+
await nextTick()
1683+
// when async resolve,it should be <div>async</div>
1684+
expect(serializeInner(root)).toBe('<div>async</div>')
1685+
1686+
viewRef.value = 1
1687+
await nextTick() //TypeError: Cannot read properties of null (reading 'parentNode'),This has been fixed
1688+
expect(serializeInner(root)).toBe(`<div>sync</div>`)
1689+
})
1690+
16411691
describe('warnings', () => {
16421692
// base function to check if a combination of slots warns or not
16431693
function baseCheckWarn(

packages/runtime-core/src/components/Suspense.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export interface SuspenseProps {
4747

4848
export const isSuspense = (type: any): boolean => type.__isSuspense
4949

50+
// incrementing unique id for every pending branch
51+
let suspenseId = 0
52+
5053
// Suspense exposes a component-like API, and is treated like a component
5154
// in the compiler, but internally it's a special built-in type that hooks
5255
// directly into the renderer.
@@ -249,7 +252,8 @@ function patchSuspense(
249252
}
250253
} else {
251254
// toggled before pending tree is resolved
252-
suspense.pendingId++
255+
// increment pending ID. this is used to invalidate async callbacks
256+
suspense.pendingId = suspenseId++
253257
if (isHydrating) {
254258
// if toggled before hydration is finished, the current DOM tree is
255259
// no longer valid. set it as the active branch so it will be unmounted
@@ -259,7 +263,6 @@ function patchSuspense(
259263
} else {
260264
unmount(pendingBranch, parentComponent, suspense)
261265
}
262-
// increment pending ID. this is used to invalidate async callbacks
263266
// reset suspense state
264267
suspense.deps = 0
265268
// discard effects from pending branch
@@ -350,7 +353,11 @@ function patchSuspense(
350353
triggerEvent(n2, 'onPending')
351354
// mount pending branch in off-dom container
352355
suspense.pendingBranch = newBranch
353-
suspense.pendingId++
356+
if (newBranch.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
357+
suspense.pendingId = newBranch.component!.suspenseId!
358+
} else {
359+
suspense.pendingId = suspenseId++
360+
}
354361
patch(
355362
null,
356363
newBranch,

0 commit comments

Comments
 (0)