Lifecycle Hooks

This section documents the current Vue 3.x release line as published at the official Vue.js documentation, which is the reference these pages are written and verified against. No specific patch version is pinned. The Composition API with <script setup> is the authoring style used throughout; the Options API is shown only as a contrast.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, since Vue and its ecosystem iterate quickly.

This section’s bibliography lists the reference material consulted while preparing these pages.

Every component instance moves through a fixed sequence: it is created, mounted into the DOM, updated as its reactive state changes, and finally unmounted. Lifecycle hooks run your code at each of those points — fetch data, attach and detach non-Vue listeners, integrate a third-party widget, clear timers. The reference is Lifecycle Hooks and the lifecycle API.

The phases

  • Create. Props are resolved and reactive state and the setup() scope are established. No DOM yet.

  • Mount. Vue creates the DOM nodes and inserts them into the page; afterwards template refs are populated.

  • Update. A reactive dependency used by the render changed, so Vue re-runs the render function and patches the DOM.

  • Unmount. The instance is torn down: its DOM is removed, and its watchers and lifecycle-registered effects are stopped.

Each phase has a before hook that fires just ahead of the work and a completion hook that fires just after.

Registering hooks

In <script setup> (or setup()), import each hook and call it with a callback. The call binds the callback to the current instance, which is why hooks must be called synchronously during setup — never inside await, setTimeout, or a .then().

<script setup>
import {
  onBeforeMount, onMounted,
  onBeforeUpdate, onUpdated,
  onBeforeUnmount, onUnmounted
} from 'vue'

onBeforeMount(() => { /* DOM not created yet */ })
onMounted(() => { /* elements and template refs are ready */ })
onBeforeUpdate(() => { /* state changed, DOM not patched yet */ })
onUpdated(() => { /* DOM back in sync with state */ })
onBeforeUnmount(() => { /* instance still fully functional */ })
onUnmounted(() => { /* detach global listeners, clear intervals */ })
</script>

The same hook can be registered more than once; the callbacks run in registration order. Registering a hook from inside a composable works because the composable is itself called synchronously from setup. See onMounted and Registering Lifecycle Hooks. This does not:

setup() {
  setTimeout(() => {
    // warns: "onMounted is called when there is no active component instance"
    onMounted(() => {})
  })
}

onMounted, onUpdated, and onBeforeUnmount do not run during server-side rendering.

Error and debug hooks

  • onErrorCaptured(fn) — fires when an error propagating from any descendant is caught. It receives (err, instance, info); return false to stop the error propagating further.

  • onRenderTracked(fn) / onRenderTriggered(fn) — development only. tracked fires as each reactive dependency is registered by the render; triggered fires when one of them causes a re-render. Both get a DebuggerEvent, which is how you find out why a component re-rendered.

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

onErrorCaptured((err, instance, info) => {
  report(err, info)
  return false   // handled here -- do not propagate
})

onRenderTriggered((e) => {
  console.log('re-render triggered by', e.type, e.key)
})
</script>

KeepAlive hooks

A component cached by <KeepAlive> is not unmounted when you navigate away from it — it is deactivated, and activated again when shown. onActivated(fn) and onDeactivated(fn) fire on that transition (and also on the initial mount and final unmount), for the cached component and all its descendants. See Components Basics for <KeepAlive> around <component :is>.

import { onActivated, onDeactivated } from 'vue'

onActivated(() => resumePolling())
onDeactivated(() => pausePolling())

The SSR hook

onServerPrefetch(fn) registers an async function that runs on the server before the component renders; its returned promise is awaited, so the data is present in the server-rendered HTML. Client-only hooks such as onMounted are skipped on the server, so pair it with a client fallback.

import { ref, onServerPrefetch, onMounted } from 'vue'

const data = ref(null)

onServerPrefetch(async () => {
  data.value = await fetchOnServer()   // awaited during SSR
})

onMounted(async () => {
  if (!data.value) data.value = await fetchOnClient()   // hydration fallback
})

The lifecycle at a glance

flowchart TD setup["setup() / script setup"] --> created["beforeCreate then created
(Options API; state ready, no DOM)"] created --> beforeMount["onBeforeMount"] beforeMount --> ssr{"server-side
rendering?"} ssr -- "yes" --> prefetch["onServerPrefetch awaited
HTML sent, client then hydrates"] ssr -- "no" --> dom["create and insert DOM nodes"] prefetch --> dom dom --> mounted["onMounted
DOM and template refs ready"] mounted --> active["mounted and reactive"] active -- "render dependency changes" --> beforeUpdate["onBeforeUpdate"] beforeUpdate --> updated["onUpdated
DOM patched"] updated --> active active -- "cached by KeepAlive, navigated away" --> deactivated["onDeactivated"] deactivated -- "shown again" --> activated["onActivated"] activated --> active active -- "removed by parent" --> beforeUnmount["onBeforeUnmount"] beforeUnmount --> unmounted["onUnmounted
watchers and effects stopped"]

Options API names

Registering a hook in setup is equivalent to the matching Options API option. The on-prefixed camelCase name maps to the bare name, with two exceptions — there is no setup-side pair for beforeCreate or created, because their timing is setup().

Composition API Options API Fires

 — 

beforeCreate

before reactive state is set up

(body of setup)

created

state ready, no DOM

onBeforeMount

beforeMount

just before first render to DOM

onMounted

mounted

DOM inserted, refs available

onBeforeUpdate

beforeUpdate

state changed, DOM not yet patched

onUpdated

updated

DOM patched to match state

onBeforeUnmount

beforeUnmount

instance still intact

onUnmounted

unmounted

instance and effects torn down

onErrorCaptured

errorCaptured

error caught from a descendant

onRenderTracked

renderTracked

dev only — dependency tracked

onRenderTriggered

renderTriggered

dev only — dependency triggered a re-render

onActivated

activated

KeepAlive-cached instance shown

onDeactivated

deactivated

KeepAlive-cached instance hidden

onServerPrefetch

serverPrefetch

SSR, before render, awaited

See also

  • Template Refs — refs first become non-null in onMounted.

  • Watchers — watchers created in setup are disposed with the instance.

  • Components Basics — <KeepAlive> and the activate / deactivate cycle.