I have this view:
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<suspense>
<template #default>
{{ pages }}
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</ion-page>
</template>
...
async setup() {
const storageRef = storage.ref();
const bookRef = storageRef.child("content/books/bk0000001");
const pages = await bookRef.listAll();
console.log({ pages }); // is logged correctly
return { pages }
}
Although it seems to load the content fine but the template is not rendered, the page remains empty neither the default
not the fallback
content is displayed.
What am I doing wrong?
When a component's setup()
is async
, the component has to be within a <suspense>
in the parent of the component (not in the component itself).
You should move the {{ pages }}
markup and the data fetching from the async setup()
into its own component:
<!-- AsyncPages.vue -->
<template>
<ul>
<li v-for="page in pages" :key="page.id">{{ page.title }}</li>
</ul>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
async setup() {
const resp = await fetch('https://jsonplaceholder.typicode.com/posts')
const pages = await resp.json()
return { pages }
}
})
</script>
And update the parent to use the new component in a <suspense>
:
<!-- Parent.vue -->
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<suspense>
<template #default>
<AsyncPages />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</ion-page>
</template>
<script>
import { defineComponent } from 'vue'
import AsyncPages from '@/components/AsyncPages.vue'
export default defineComponent({
components: {
AsyncPages
}
})
</script>
Alternatively, you could rewrite the above into a non-async setup()
, using an onMounted
async hook instead:
<!-- Parent.vue -->
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<ul v-if="pages">
<li v-for="page in pages" :key="page.id">{{ page.title }}</li>
</ul>
<div v-else>Loading...</div>
</ion-page>
</template>
<script>
import { defineComponent, onMounted, ref } from 'vue'
export default defineComponent({
setup() {
const pages = ref(null)
onMounted(async () => {
const resp = await fetch('https://jsonplaceholder.typicode.com/posts')
pages.value = await resp.json()
})
return { pages }
}
})
</script>