]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): should call Suspense fallback unmount hook (#1061)
authorunderfin <2218301630@qq.com>
Fri, 1 May 2020 20:20:16 +0000 (04:20 +0800)
committerGitHub <noreply@github.com>
Fri, 1 May 2020 20:20:16 +0000 (16:20 -0400)
fix #1059

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

index cb8ece4873e5d4d6633aa6602e128fa6a85ee9a8..8c5eecac56d9611356e30bf8f4841073435280a6 100644 (file)
@@ -221,6 +221,57 @@ describe('Suspense', () => {
     ])
   })
 
+  // #1059
+  test('mounted/updated hooks & fallback component', async () => {
+    const deps: Promise<any>[] = []
+    const calls: string[] = []
+    const toggle = ref(true)
+
+    const Async = {
+      async setup() {
+        const p = new Promise(r => setTimeout(r, 1))
+        // extra tick needed for Node 12+
+        deps.push(p.then(() => Promise.resolve()))
+
+        await p
+        return () => h('div', 'async')
+      }
+    }
+
+    const Fallback = {
+      setup() {
+        onMounted(() => {
+          calls.push('mounted')
+        })
+
+        onUnmounted(() => {
+          calls.push('unmounted')
+        })
+        return () => h('div', 'fallback')
+      }
+    }
+
+    const Comp = {
+      setup() {
+        return () =>
+          h(Suspense, null, {
+            default: toggle.value ? h(Async) : null,
+            fallback: h(Fallback)
+          })
+      }
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(Comp), root)
+    expect(serializeInner(root)).toBe(`<div>fallback</div>`)
+    expect(calls).toEqual([`mounted`])
+
+    await Promise.all(deps)
+    await nextTick()
+    expect(serializeInner(root)).toBe(`<div>async</div>`)
+    expect(calls).toEqual([`mounted`, `unmounted`])
+  })
+
   test('content update before suspense resolve', async () => {
     const Async = defineAsyncComponent({
       props: { msg: String },
@@ -316,7 +367,7 @@ describe('Suspense', () => {
     await nextTick()
     expect(serializeInner(root)).toBe(`<!---->`)
     // should discard effects (except for immediate ones)
-    expect(calls).toEqual(['immediate effect'])
+    expect(calls).toEqual(['immediate effect', 'watch callback', 'unmounted'])
   })
 
   test('unmount suspense after resolve', async () => {
index 4152b7ded553b137d0e5378a88dfde5b5e17ba16..de2139688552328de16792ba4476c06ce72774e6 100644 (file)
@@ -1856,9 +1856,9 @@ function baseCreateRenderer(
     ) {
       queuePostRenderEffect(da, parentSuspense)
     }
-    queuePostFlushCb(() => {
+    queuePostRenderEffect(() => {
       instance.isUnmounted = true
-    })
+    }, parentSuspense)
 
     // A component with async dep inside a pending suspense is unmounted before
     // its async dep resolves. This should remove the dep from the suspense, and