Lifecycle
A component is created, mounted to the DOM, and eventually destroyed. Svelte provides lifecycle functions for the key moments — but with a twist: in Svelte 5, the $effect rune (Chapter 3) handles many cases that would be lifecycle hooks in other frameworks, because an effect with a cleanup return already covers "run on mount, clean up on destroy."
onMount — After the Component Is in the DOM
onMount runs a callback once, after the component is first inserted into the DOM — the standard place for an initial data fetch, the equivalent of React's useEffect(() => {...}, []), Vue's onMounted, and Angular's ngOnInit. Unlike the others, onMount is imported from 'svelte' (it's a function, not a rune). By the time it runs, the DOM exists, so it's also safe to measure or access elements here.
onMount elsewhere can just live at the top of <script>: $state, $derived, and plain setup run once when the component is created, before it mounts. Reach for onMount specifically when you need the DOM to exist first (measuring an element, initializing a canvas, a third-party widget) or want to defer work until after the first render — and note onMount does not run during server-side rendering, which makes it the right place for browser-only code.
onDestroy — Cleanup Before Removal
onDestroy runs just before the component is removed — the place for cleanup, mirroring Vue's onUnmounted and Angular's ngOnDestroy. The universal rule applies: anything that "starts" something ongoing (a timer, a listener, a subscription) needs a matching "stop" here, or it leaks.
The Cleaner Way — onMount Returning Cleanup
A neat shortcut: if onMount returns a function, Svelte calls it on destroy automatically — so setup and teardown live together in one place, without a separate onDestroy. This is exactly React's useEffect cleanup-return pattern, and it keeps the timer's start and stop side by side.
$effect Often Replaces Lifecycle Entirely
Because $effect (Chapter 3) runs after mount and its returned cleanup runs on destroy, an effect frequently does the job of onMount + onDestroy together — and re-runs if its dependencies change, which a one-time onMount doesn't. The practical guidance for Svelte 5: use $effect for reactive setup/teardown (anything that should respond to changing state); use onMount for one-time, mount-only, browser-only setup (DOM measurement, SSR-sensitive code). You'll reach for onDestroy on its own fairly rarely now.
beforeUpdate and afterUpdate hooks (run around each re-render). Svelte 5 deprecated them in favor of $effect (and $effect.pre for "before DOM update"), since reactive effects express the same intent more precisely. onMount and onDestroy remain; beforeUpdate/afterUpdate are the ones to replace with effects in modern code.
| Svelte 5 | React | Vue | Angular |
|---|---|---|---|
| top of <script> | component body | top of <script setup> | constructor |
| onMount | useEffect(.., []) | onMounted | ngOnInit |
| onDestroy / onMount cleanup return | cleanup return | onUnmounted | ngOnDestroy |
| $effect (+ cleanup) | useEffect (reactive) | watchEffect | effect() |
Coding Challenges
Build a component that fetches a list from any free public API in onMount, storing it in a $state for display, with a loading state shown until the data arrives.
📄 View solutionBuild a Clock component that starts a setInterval in onMount (updating a time $state every second) and clears it by returning a cleanup function from onMount. Toggle the component with {#if} in a parent to confirm the ticking stops when removed.
📄 View solutionBuild a component that tracks the window's width using a resize listener — implemented two ways for comparison: once with onMount + onDestroy, and once with a single $effect that returns its cleanup. Display the live width.
📄 View solutionChapter 9 Quick Reference
- Top-of-
<script>code runs at creation, before mount - onMount (imported from
'svelte') — runs once after mount; browser-only, skipped during SSR - onDestroy — runs before removal; or return a cleanup function from
onMountinstead - $effect with a cleanup return often replaces
onMount+onDestroy, and re-runs reactively - Guidance:
$effectfor reactive setup/teardown;onMountfor one-time, mount-only, browser-only work - Svelte 4's
beforeUpdate/afterUpdateare replaced by$effect/$effect.pre - Next chapter: shared reactive logic in
.svelte.jsmodules