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/lifecycle-hooks-synchronous-registration.md
1---2title: Register Lifecycle Hooks Synchronously During Setup3impact: HIGH4impactDescription: Asynchronously registered lifecycle hooks will never execute5type: capability6tags: [vue3, composition-api, lifecycle, onMounted, onUnmounted, async, setup]7---89# Register Lifecycle Hooks Synchronously During Setup1011**Impact: HIGH** - Lifecycle hooks registered asynchronously (e.g., inside setTimeout, after await) will never be called because Vue cannot associate them with the component instance. This leads to silent failures where expected initialization or cleanup code never runs.1213In Vue 3's Composition API, lifecycle hooks like `onMounted`, `onUnmounted`, `onUpdated`, etc. must be registered synchronously during component setup. The hook registration doesn't need to be lexically inside `setup()` or `<script setup>`, but the call stack must be synchronous and originate from within setup.1415## Task Checklist1617- [ ] Register all lifecycle hooks at the top level of setup() or `<script setup>`18- [ ] Never register hooks inside setTimeout, setInterval, or Promise callbacks19- [ ] When calling composables that use lifecycle hooks, call them synchronously20- [ ] Hooks CAN be in external functions if called synchronously from setup2122**Incorrect:**23```javascript24// WRONG: Hook registered asynchronously - will NEVER execute25import { onMounted } from 'vue'2627export default {28async setup() {29// After await, we're in a different call stack30const data = await fetchInitialData()3132// This hook will NOT be registered!33onMounted(() => {34console.log('This will never run')35})36}37}38```3940```javascript41// WRONG: Hook registered in setTimeout - will NEVER execute42import { onMounted } from 'vue'4344export default {45setup() {46setTimeout(() => {47// This is asynchronous - hook won't be registered!48onMounted(() => {49initializeChart()50})51}, 100)52}53}54```5556```javascript57// WRONG: Hook registered in Promise callback58import { onMounted } from 'vue'5960export default {61setup() {62fetchConfig().then(() => {63// Asynchronous! This will silently fail64onMounted(() => {65applyConfig()66})67})68}69}70```7172**Correct:**73```javascript74// CORRECT: Hook registered synchronously at top level75import { onMounted, ref } from 'vue'7677export default {78setup() {79const data = ref(null)8081// Register hook synchronously FIRST82onMounted(async () => {83// Async operations are fine INSIDE the hook84data.value = await fetchInitialData()85initializeChart()86})8788return { data }89}90}91```9293```vue94<!-- CORRECT: <script setup> - hooks at top level -->95<script setup>96import { onMounted, onUnmounted, ref } from 'vue'9798const isReady = ref(false)99100// These are synchronous during script setup execution101onMounted(() => {102isReady.value = true103})104105onUnmounted(() => {106cleanup()107})108</script>109```110111```javascript112// CORRECT: Hook in external function called synchronously from setup113import { onMounted, onUnmounted } from 'vue'114115function useWindowResize(callback) {116// This is fine - it's called synchronously from setup117onMounted(() => {118window.addEventListener('resize', callback)119})120121onUnmounted(() => {122window.removeEventListener('resize', callback)123})124}125126export default {127setup() {128// Composable called synchronously - hooks will be registered129useWindowResize(handleResize)130}131}132```133134## Multiple Hooks Are Allowed135136```javascript137// CORRECT: You can register the same hook multiple times138import { onMounted } from 'vue'139140export default {141setup() {142// Both will run, in order of registration143onMounted(() => {144initializeA()145})146147onMounted(() => {148initializeB()149})150}151}152```153154## Reference155- [Vue.js Lifecycle Hooks](https://vuejs.org/guide/essentials/lifecycle.html)156- [Composition API Lifecycle Hooks](https://vuejs.org/api/composition-api-lifecycle.html)157