Home
Blogs
Series
Components
Vue Lifecycle Hooks: An Overview

Vue Lifecycle Hooks: An Overview

A clear map of all Vue 3 lifecycle hooks to understand when to use each one.

Vue lifecycle hooks: practical guide and when to use each one

Why this matters

Understanding the component lifecycle helps you know exactly when to run each type of logic: initialization, DOM access, API synchronization, side effect cleanup, or debugging.

Core concept

A Vue 3 component goes through several phases:

  1. Creation
  2. Mounting
  3. Updating
  4. Unmounting

There are also special hooks for:

  • Components cached with <KeepAlive>
  • Error handling
  • Reactive render debugging
  • SSR (Server-Side Rendering)

In the next sections, we will see when each hook runs and what it is for, with examples.

Component creation

In this phase, Vue creates the component instance and sets up reactivity, but the DOM does not exist yet.

This is where you usually initialize state, configuration, or early requests.

beforeCreate

Runs before Vue configures reactivity.

App.vue
<script>
export default {
  beforeCreate() {
    console.log('The component is starting')
  }
}
</script>

beforeCreate is not available in Composition API, because setup() runs before any other hook.

created

Reactive state is already available, but the DOM still does not exist.

It is commonly used for:

  • HTTP requests
  • State initialization
  • Business logic preparation
App.vue
<script>
export default {
  data() {
    return {
      users: []
    }
  },
  async created() {
    this.users = await fetch('/api/users').then(r => r.json())
  }
}
</script>

created is not available in Composition API, because setup() runs before any other hook.

setup()

It is the main entry point in Composition API.

Here you define:

  • Reactive state
  • Composables
  • Watchers
  • Initial component logic
App.vue
<script setup>
import { ref } from 'vue'

const count = ref(0)

console.log('Setup executed')
</script>

setup() is not available in Options API, because it is exclusive to Composition API.

Component mounting

In this phase Vue creates and inserts the component DOM.

At this point it is safe to use:

  • Browser APIs
  • External libraries
  • DOM manipulation

onBeforeMount / beforeMount

Runs right before inserting the DOM into the page.

It is not very common, but it can be useful for final pre-render logic.

<script setup>
import { onBeforeMount } from 'vue'

onBeforeMount(() => {
  console.log('Component is about to mount')
})
</script>
<script>
export default {
  beforeMount() {
    console.log('Before mounting the component')
  }
}
</script>

onMounted / mounted

Runs after the component has been inserted into the DOM.

This is one of the most used hooks.

Typical uses:

  • Initializing charts
  • Registering listeners
  • Focusing inputs
  • Integrating third-party libraries
<script setup>
import { onMounted } from 'vue'

onMounted(() => {
  console.log('Component mounted in the DOM')
})
</script>
<script>
export default {
  mounted() {
    console.log('Component mounted')
  }
}
</script>

Component update

When reactive state changes, Vue re-renders the component.

These hooks let you react before or after the DOM changes.

onBeforeUpdate / beforeUpdate

Runs before Vue updates the DOM.

Can be used to inspect previous state.

<script setup>
import { onBeforeUpdate } from 'vue'

onBeforeUpdate(() => {
  console.log('Before updating the DOM')
})
</script>
<script>
export default {
  beforeUpdate() {
    console.log('Before update')
  }
}
</script>

onUpdated / updated

Runs after Vue updates the DOM.

Useful when you need to measure or interact with the updated DOM.

onUpdated should not be used as a replacement for watch.

<script setup>
import { onUpdated } from 'vue'

onUpdated(() => {
  console.log('DOM has been updated')
})
</script>
<script>
export default {
  updated() {
    console.log('DOM updated')
  }
}
</script>

Component unmounting

When a component stops existing, Vue runs cleanup hooks.

This is key to avoid memory leaks.

onBeforeUnmount / beforeUnmount

Runs right before destroying the component.

<script setup>
import { onBeforeUnmount } from 'vue'

onBeforeUnmount(() => {
  console.log('Component will be destroyed')
})
</script>
<script>
export default {
  beforeUnmount() {
    console.log('Before unmounting')
  }
}
</script>

onUnmounted / unmounted

Runs after the component has been destroyed.

Ideal for cleaning:

  • Timers
  • Sockets
  • Event listeners
<script setup>
import { onMounted, onUnmounted } from 'vue'

let timer

onMounted(() => {
  timer = setInterval(() => {
    console.log('tick')
  }, 1000)
})

onUnmounted(() => {
  clearInterval(timer)
})
</script>
<script>
export default {
  mounted() {
    this.timer = setInterval(() => {
      console.log('tick')
    }, 1000)
  },
  unmounted() {
    clearInterval(this.timer)
  }
}
</script>

<KeepAlive> hooks

When a component is inside <KeepAlive>, it is not destroyed, it is only activated or deactivated.

onActivated / activated

Runs when the component becomes active again.

<script setup>
import { onActivated } from 'vue'

onActivated(() => {
  console.log('Component activated again')
})
</script>
<script>
export default {
  activated() {
    console.log('Component activated')
  }
}
</script>

onDeactivated / deactivated

Runs when the component is hidden but stays in memory.

<script setup>
import { onDeactivated } from 'vue'

onDeactivated(() => {
  console.log('Component deactivated')
})
</script>
<script>
export default {
  deactivated() {
    console.log('Component deactivated')
  }
}
</script>

Error handling

onErrorCaptured / errorCaptured

Allows capturing errors from child components.

<script setup>
import { onErrorCaptured } from 'vue'

onErrorCaptured((error) => {
  console.error('Captured error:', error)
  return false
})
</script>
<script>
export default {
  errorCaptured(error) {
    console.error('Captured error:', error)
    return false
  }
}
</script>

Render debugging hooks

These hooks help understand why a component is re-rendering.

They should not be used by default in production.

onRenderTracked

Runs when Vue tracks a reactive dependency during render.

<script setup>
import { onRenderTracked } from 'vue'

onRenderTracked((event) => {
  console.debug('Tracked dependency:', event.key)
})
</script>
<script>
export default {
  renderTracked(event) {
    console.debug('Tracked dependency:', event.key)
  }
}
</script>

onRenderTriggered

Runs when a dependency triggers a re-render.

<script setup>
import { onRenderTriggered } from 'vue'

onRenderTriggered((event) => {
  console.debug('Re-render caused by:', event.key)
})
</script>
<script>
export default {
  renderTriggered(event) {
    console.debug('Re-render caused by:', event.key)
  }
}
</script>

SSR (Server-Side Rendering)

onServerPrefetch / serverPrefetch

Allows loading data before rendering HTML on the server.

This prevents empty screens during first render.

<script setup>
import { onServerPrefetch } from 'vue'

onServerPrefetch(async () => {
  await fetch('/api/data')
})
</script>
<script>
export default {
  async serverPrefetch() {
    await fetch('/api/data')
  }
}
</script>

When to use hooks (and when not to)

Use them when:

  • You need real DOM access (onMounted)
  • You need resource cleanup (onUnmounted)
  • You are working with SSR (onServerPrefetch)
  • You need to react to component lifecycle phases

Avoid them when:

  • A computed solves the problem
  • A watch is enough
  • You only need to react to specific state changes

Hooks coordinate lifecycle moments and should not hold all component logic.

Summary

Lifecycle hooks let you control key component moments:

PhaseMain hooks
Creationsetup, created
MountingonMounted, mounted
UpdatingonUpdated, updated
UnmountingonUnmounted, unmounted
CacheonActivated, onDeactivated
SSRonServerPrefetch

If you are not sure which hook to use, ask first: At what point in the component lifecycle do I need this logic to run?

Edit this page on GitHub

Found an issue or want to improve this post? You can propose changes directly.