Skip to content

Commit 8b85aae

Browse files
authored
fix(runtime-core): should call Suspense fallback unmount hook (#1061)
fix #1059
1 parent b40fcbc commit 8b85aae

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

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

+52-1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,57 @@ describe('Suspense', () => {
221221
])
222222
})
223223

224+
// #1059
225+
test('mounted/updated hooks & fallback component', async () => {
226+
const deps: Promise<any>[] = []
227+
const calls: string[] = []
228+
const toggle = ref(true)
229+
230+
const Async = {
231+
async setup() {
232+
const p = new Promise(r => setTimeout(r, 1))
233+
// extra tick needed for Node 12+
234+
deps.push(p.then(() => Promise.resolve()))
235+
236+
await p
237+
return () => h('div', 'async')
238+
}
239+
}
240+
241+
const Fallback = {
242+
setup() {
243+
onMounted(() => {
244+
calls.push('mounted')
245+
})
246+
247+
onUnmounted(() => {
248+
calls.push('unmounted')
249+
})
250+
return () => h('div', 'fallback')
251+
}
252+
}
253+
254+
const Comp = {
255+
setup() {
256+
return () =>
257+
h(Suspense, null, {
258+
default: toggle.value ? h(Async) : null,
259+
fallback: h(Fallback)
260+
})
261+
}
262+
}
263+
264+
const root = nodeOps.createElement('div')
265+
render(h(Comp), root)
266+
expect(serializeInner(root)).toBe(`<div>fallback</div>`)
267+
expect(calls).toEqual([`mounted`])
268+
269+
await Promise.all(deps)
270+
await nextTick()
271+
expect(serializeInner(root)).toBe(`<div>async</div>`)
272+
expect(calls).toEqual([`mounted`, `unmounted`])
273+
})
274+
224275
test('content update before suspense resolve', async () => {
225276
const Async = defineAsyncComponent({
226277
props: { msg: String },
@@ -316,7 +367,7 @@ describe('Suspense', () => {
316367
await nextTick()
317368
expect(serializeInner(root)).toBe(`<!---->`)
318369
// should discard effects (except for immediate ones)
319-
expect(calls).toEqual(['immediate effect'])
370+
expect(calls).toEqual(['immediate effect', 'watch callback', 'unmounted'])
320371
})
321372

322373
test('unmount suspense after resolve', async () => {

packages/runtime-core/src/renderer.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1856,9 +1856,9 @@ function baseCreateRenderer(
18561856
) {
18571857
queuePostRenderEffect(da, parentSuspense)
18581858
}
1859-
queuePostFlushCb(() => {
1859+
queuePostRenderEffect(() => {
18601860
instance.isUnmounted = true
1861-
})
1861+
}, parentSuspense)
18621862

18631863
// A component with async dep inside a pending suspense is unmounted before
18641864
// its async dep resolves. This should remove the dep from the suspense, and

0 commit comments

Comments
 (0)