Suspense

Wait for Async Setup Before Rendering

Suspense

`<Suspense>` lets a child component await async work in setup and shows a fallback meanwhile — no manual loading flags.

4 min read Level 3/5 #vue#suspense#async
What you'll learn
  • Make a component's setup async
  • Wrap with `<Suspense>` and provide a
  • Combine with async components for lazy loading

<Suspense> is Vue’s built-in boundary for async components. The child can await data in its setup, and Suspense renders a fallback until the promise resolves.

Async setup

A <script setup> block with a top-level await makes the whole component async.

<!-- UserCard.vue -->
<script setup lang="ts">
const res = await fetch(`/api/me`)
const user = await res.json()
</script>

<template>
  <p>Hello {{ user.name }}</p>
</template>

Wrap With Suspense

<!-- Parent.vue -->
<template>
  <Suspense>
    <template #default>
      <UserCard />
    </template>
    <template #fallback>
      <p>Loading…</p>
    </template>
  </Suspense>
</template>

While the child’s setup is pending, the #fallback slot renders. Once the promise resolves, Suspense swaps to #default.

Lifecycle Hooks

Suspense emits resolve, pending, and fallback events you can listen to:

<Suspense @resolve="onLoaded" @pending="onPending">…</Suspense>

Async Components

<Suspense> also pairs with defineAsyncComponent for code-split components.

import { defineAsyncComponent } from 'vue'
const Heavy = defineAsyncComponent(() => import('./Heavy.vue'))

The fallback shows during the chunk download too — one boundary, two use cases.

Error Handling →