Bladeren bron

fix(runtime-core): should call Suspense fallback unmount hook (#1061)

fix #1059
underfin 6 jaren geleden
bovenliggende
commit
8b85aaeea9

+ 52 - 1
packages/runtime-core/__tests__/components/Suspense.spec.ts

@@ -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 () => {

+ 2 - 2
packages/runtime-core/src/renderer.ts

@@ -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