Sfoglia il codice sorgente

dx(suspense): warn when using async setup when not inside a Suspense boundary (#5565)

close #3649
Thorsten Lünborg 4 anni fa
parent
commit
053c65bc5e

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

@@ -709,7 +709,7 @@ describe('Suspense', () => {
       <div v-if="errorMessage">{{ errorMessage }}</div>
       <div v-if="errorMessage">{{ errorMessage }}</div>
       <Suspense v-else>
       <Suspense v-else>
         <div>
         <div>
-          <Async />     
+          <Async />
         </div>
         </div>
         <template #fallback>
         <template #fallback>
           <div>fallback</div>
           <div>fallback</div>
@@ -1232,4 +1232,25 @@ describe('Suspense', () => {
     await nextTick()
     await nextTick()
     expect(serializeInner(root)).toBe(`<div>parent<!----></div>`)
     expect(serializeInner(root)).toBe(`<div>parent<!----></div>`)
   })
   })
+
+  test('warn if using async setup when not in a Suspense boundary', () => {
+    const Child = {
+      name: 'Child',
+      async setup() {
+        return () => h('div', 'child')
+      }
+    }
+    const Parent = {
+      setup() {
+        return () => h('div', [h(Child)])
+      }
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(Parent), root)
+
+    expect(
+      `A component with async setup() must be nested in a <Suspense>`
+    ).toHaveBeenWarned()
+  })
 })
 })

+ 9 - 1
packages/runtime-core/src/component.ts

@@ -654,7 +654,6 @@ function setupStatefulComponent(
 
 
     if (isPromise(setupResult)) {
     if (isPromise(setupResult)) {
       setupResult.then(unsetCurrentInstance, unsetCurrentInstance)
       setupResult.then(unsetCurrentInstance, unsetCurrentInstance)
-
       if (isSSR) {
       if (isSSR) {
         // return the promise so server-renderer can wait on it
         // return the promise so server-renderer can wait on it
         return setupResult
         return setupResult
@@ -668,6 +667,15 @@ function setupStatefulComponent(
         // async setup returned Promise.
         // async setup returned Promise.
         // bail here and wait for re-entry.
         // bail here and wait for re-entry.
         instance.asyncDep = setupResult
         instance.asyncDep = setupResult
+        if (__DEV__ && !instance.suspense) {
+          const name = Component.name ?? 'Anonymous'
+          warn(
+            `Component <${name}>: setup function returned a promise, but no ` +
+              `<Suspense> boundary was found in the parent component tree. ` +
+              `A component with async setup() must be nested in a <Suspense> ` +
+              `in order to be rendered.`
+          )
+        }
       } else if (__DEV__) {
       } else if (__DEV__) {
         warn(
         warn(
           `setup() returned a Promise, but the version of Vue you are using ` +
           `setup() returned a Promise, but the version of Vue you are using ` +