43

Problem

I use async setup() in Vue.js 3, but I got my HTML content to disappear. My component template did not insert to HTML, but when I remove the async and await prefix, my HTML content comes back. How can I fix this?

async setup () {
    const data = ref(null)
    try {
        const res = await fetch('api')
        data.value = res.json()
    }
    catch (e) {
        console.error(e)
    }
    return {
        data
    }
}

I've tried

  1. I checked fetch, and it returned the correct response
  2. I've tried <Suspense> tag, but still the same problem
Paolo
  • 20,112
  • 21
  • 72
  • 113
g6165310
  • 441
  • 1
  • 4
  • 4

2 Answers2

59

Your component's async setup() looks fine other than the missing await res.json(), which still wouldn't cause the problem you're seeing. I suspect your usage of <Suspense> is incorrect.

To use async setup() in a component, the parent component must use that component in a <Suspense> tag:

<!-- Parent.vue -->
<template>
 <Suspense>
   <MyAsyncComponent />
 </Suspense>
</template>

You could also use the default and fallback slots of <Suspense> to show a loading indicator while waiting for the child component's setup to resolve:

<!-- Parent.vue -->
<template>
 <Suspense>
   <template #default>
     <MyAsyncComponent />
   </template>
   <template #fallback>
     <span>Loading...</span>
   </template>
 </Suspense>
</template>

demo

tony19
  • 125,647
  • 18
  • 229
  • 307
4

File parent.vue

<template>
  <!-- parent add <suspense> -->
  <suspense>
    <child />
  </suspense>
</template>

<script>
import Child from './child.vue'

export default {
  components: {
    child
  },
  setup() {
    return {}
  }
}
</script>

File child.vue

<template>
  <div>child</div>
</template>

<script>
export default {
  async setup() {
    return {}
  }
}
</script>

For child.vue, use async setup.... For parent.vue, you need to add <suspense> to child.vue.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sinosaurus
  • 1,139
  • 1
  • 7
  • 11