Skip to content

Commit ab6e927

Browse files
authoredJun 21, 2021
fix(Suspense): emit initial fallback and pending events (#3965)
Fix #3964
1 parent 43e2a72 commit ab6e927

File tree

2 files changed

+81
-12
lines changed

2 files changed

+81
-12
lines changed
 

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

+64
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,70 @@ describe('Suspense', () => {
6969
expect(serializeInner(root)).toBe(`<div>async</div>`)
7070
})
7171

72+
test('emits events', async () => {
73+
const Async = defineAsyncComponent({
74+
render() {
75+
return h('div', 'async')
76+
}
77+
})
78+
79+
const onFallback = jest.fn()
80+
const onResolve = jest.fn()
81+
const onPending = jest.fn()
82+
83+
const show = ref(true)
84+
const Comp = {
85+
setup() {
86+
return () =>
87+
h(
88+
Suspense,
89+
{
90+
onFallback,
91+
onResolve,
92+
onPending,
93+
// force displaying the fallback right away
94+
timeout: 0
95+
},
96+
{
97+
default: () => (show.value ? h(Async) : null),
98+
fallback: h('div', 'fallback')
99+
}
100+
)
101+
}
102+
}
103+
104+
const root = nodeOps.createElement('div')
105+
render(h(Comp), root)
106+
expect(onFallback).toHaveBeenCalledTimes(1)
107+
expect(onPending).toHaveBeenCalledTimes(1)
108+
expect(onResolve).toHaveBeenCalledTimes(0)
109+
110+
await Promise.all(deps)
111+
await nextTick()
112+
expect(onFallback).toHaveBeenCalledTimes(1)
113+
expect(onPending).toHaveBeenCalledTimes(1)
114+
expect(onResolve).toHaveBeenCalledTimes(1)
115+
116+
show.value = false
117+
await nextTick()
118+
expect(onFallback).toHaveBeenCalledTimes(1)
119+
expect(onPending).toHaveBeenCalledTimes(2)
120+
expect(onResolve).toHaveBeenCalledTimes(2)
121+
122+
deps.length = 0
123+
show.value = true
124+
await nextTick()
125+
expect(onFallback).toHaveBeenCalledTimes(2)
126+
expect(onPending).toHaveBeenCalledTimes(3)
127+
expect(onResolve).toHaveBeenCalledTimes(2)
128+
129+
await Promise.all(deps)
130+
await nextTick()
131+
expect(onFallback).toHaveBeenCalledTimes(2)
132+
expect(onPending).toHaveBeenCalledTimes(3)
133+
expect(onResolve).toHaveBeenCalledTimes(3)
134+
})
135+
72136
test('nested async deps', async () => {
73137
const calls: string[] = []
74138

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

+17-12
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ export const Suspense = ((__FEATURE_SUSPENSE__
9494
new (): { $props: VNodeProps & SuspenseProps }
9595
}
9696

97+
function triggerEvent(
98+
vnode: VNode,
99+
name: 'onResolve' | 'onPending' | 'onFallback'
100+
) {
101+
const eventListener = vnode.props && vnode.props[name]
102+
if (isFunction(eventListener)) {
103+
eventListener()
104+
}
105+
}
106+
97107
function mountSuspense(
98108
vnode: VNode,
99109
container: RendererElement,
@@ -137,6 +147,10 @@ function mountSuspense(
137147
// now check if we have encountered any async deps
138148
if (suspense.deps > 0) {
139149
// has async
150+
// invoke @fallback event
151+
triggerEvent(vnode, 'onPending')
152+
triggerEvent(vnode, 'onFallback')
153+
140154
// mount the fallback tree
141155
patch(
142156
null,
@@ -304,10 +318,7 @@ function patchSuspense(
304318
} else {
305319
// root node toggled
306320
// invoke @pending event
307-
const onPending = n2.props && n2.props.onPending
308-
if (isFunction(onPending)) {
309-
onPending()
310-
}
321+
triggerEvent(n2, 'onPending')
311322
// mount pending branch in off-dom container
312323
suspense.pendingBranch = newBranch
313324
suspense.pendingId++
@@ -501,10 +512,7 @@ function createSuspenseBoundary(
501512
suspense.effects = []
502513

503514
// invoke @resolve event
504-
const onResolve = vnode.props && vnode.props.onResolve
505-
if (isFunction(onResolve)) {
506-
onResolve()
507-
}
515+
triggerEvent(vnode, 'onResolve')
508516
},
509517

510518
fallback(fallbackVNode) {
@@ -521,10 +529,7 @@ function createSuspenseBoundary(
521529
} = suspense
522530

523531
// invoke @fallback event
524-
const onFallback = vnode.props && vnode.props.onFallback
525-
if (isFunction(onFallback)) {
526-
onFallback()
527-
}
532+
triggerEvent(vnode, 'onFallback')
528533

529534
const anchor = next(activeBranch!)
530535
const mountFallback = () => {

0 commit comments

Comments
 (0)
Please sign in to comment.