---
title: Top-Level await in script setup Preserves Component Context
impact: HIGH
impactDescription: Misunderstanding async context causes lifecycle hooks and watchers to silently fail
type: gotcha
tags: [vue3, composition-api, script-setup, async, await, suspense]
---
# Top-Level await in script setup Preserves Component Context
**Impact: HIGH** - In `
```
**Nested Async Breaks Context:**
```vue
```
**Correct Patterns:**
```vue
```
**setup() Function (Not script setup):**
```javascript
// In regular setup(), await ALWAYS breaks context
export default {
async setup() {
const data = ref(null)
// WRONG: Hooks after await won't register
const config = await fetchConfig()
onMounted(() => {
console.log('Never runs!') // Silent failure!
})
return { data }
}
}
// CORRECT: Register hooks before any await
export default {
async setup() {
const data = ref(null)
// Register hooks FIRST (synchronous)
onMounted(async () => {
const config = await fetchConfig()
data.value = await fetchData(config)
})
// Now you can await if needed
// But hooks must be registered before this point
return { data }
}
}
```
## Why This Happens
```javascript
// Vue tracks the "current component instance" during setup
// This is like a global variable that gets set and cleared
// During synchronous setup:
function setup() {
currentInstance = this // Vue sets this
onMounted(cb) // Uses currentInstance to register
// After await, JavaScript resumes in a microtask
await something()
// currentInstance is now null or different!
onMounted(cb) // Can't find the instance - silently fails
}
//