Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/async-component-suspense-control.md
1---2title: Suspense Overrides Async Component Loading and Error Options3impact: MEDIUM4impactDescription: Async component loading/error options are ignored under a parent Suspense, leading to missing spinners and error UIs5type: gotcha6tags: [vue3, suspense, async-components, loading, error-handling]7---89# Suspense Overrides Async Component Loading and Error Options1011**Impact: MEDIUM** - When an async component renders inside a parent `<Suspense>`, its `loadingComponent`, `errorComponent`, `delay`, and `timeout` options do not run. The parent Suspense controls loading and error UX instead.1213## Task Checklist1415- [ ] Confirm whether the async component is inside a `<Suspense>` boundary16- [ ] Use `suspensible: false` when the component must manage its own loading/error UI17- [ ] Or move loading/error UI to the parent `<Suspense>` fallback and an error boundary (`onErrorCaptured`)18- [ ] Provide a retry path for failed loads1920**Incorrect:**21```vue22<script setup>23import { defineAsyncComponent } from 'vue'2425const AsyncDashboard = defineAsyncComponent({26loader: () => import('./Dashboard.vue'),27loadingComponent: LoadingSpinner,28errorComponent: ErrorDisplay,29timeout: 300030})31</script>3233<template>34<Suspense>35<AsyncDashboard />36<template #fallback>Loading...</template>37</Suspense>38</template>39```4041**Correct (component handles its own states):**42```vue43<script setup>44import { defineAsyncComponent } from 'vue'4546const AsyncDashboard = defineAsyncComponent({47loader: () => import('./Dashboard.vue'),48loadingComponent: LoadingSpinner,49errorComponent: ErrorDisplay,50timeout: 3000,51suspensible: false52})53</script>5455<template>56<AsyncDashboard />57</template>58```5960**Correct (parent Suspense owns loading/error UI):**61```vue62<script setup>63import { onErrorCaptured, ref } from 'vue'64import AsyncDashboard from './AsyncDashboard.vue'6566const error = ref(null)6768onErrorCaptured((err) => {69error.value = err70return false71})72</script>7374<template>75<ErrorDisplay v-if="error" :error="error" />7677<Suspense v-else>78<AsyncDashboard />79<template #fallback>80<LoadingSpinner />81</template>82</Suspense>83</template>84```85