Svelte • Runtime

Lifecycle hooks

On this page

In Svelte 5, the component lifecycle consists of only two parts: Its creation and its destruction. Everything in-between — when certain state is updated — is not related to the component as a whole; only the parts that need to react to the state change are notified. This is because under the hood the smallest unit of change is actually not a component, it’s the (render) effects that the component sets up upon component initialization. Consequently, there’s no such thing as a “before update”/“after update” hook.

onMount

The onMount function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component’s initialisation (but doesn’t need to live inside the component; it can be called from an external module).

onMount does not run inside a component that is rendered on the server.

<script lang="ts">
	import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
} from 'svelte';
onMount<void>(fn: () => void | (() => any) | Promise<void>): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component has mounted');
}); </script>
<script>
	import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
} from 'svelte';
onMount<void>(fn: () => void | (() => any) | Promise<void>): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component has mounted');
}); </script>

If a function is returned from onMount, it will be called when the component is unmounted.

<script lang="ts">
	import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
} from 'svelte';
onMount<() => void>(fn: () => (() => any) | Promise<never>): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
(() => {
const const interval: NodeJS.Timeoutinterval = function setInterval<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)setInterval(() => { var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('beep');
}, 1000); return () => function clearInterval(timeout: NodeJS.Timeout | string | number | undefined): void (+1 overload)clearInterval(const interval: NodeJS.Timeoutinterval); }); </script>
<script>
	import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
} from 'svelte';
onMount<() => void>(fn: () => (() => any) | Promise<never>): void

onMount, like $effect, schedules a function to run as soon as the component has been mounted to the DOM. Unlike $effect, the provided function only runs once.

It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module). If a function is returned synchronously from onMount, it will be called when the component is unmounted.

onMount functions do not run during server-side rendering.

onMount
(() => {
const const interval: NodeJS.Timeoutinterval = function setInterval<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)setInterval(() => { var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('beep');
}, 1000); return () => function clearInterval(timeout: NodeJS.Timeout | string | number | undefined): void (+1 overload)clearInterval(const interval: NodeJS.Timeoutinterval); }); </script>

This behaviour will only work when the function passed to onMount is synchronous. async functions always return a Promise.

onDestroy

Schedules a callback to run immediately before the component is unmounted.

Out of onMount, beforeUpdate, afterUpdate and onDestroy, this is the only one that runs inside a server-side component.

<script lang="ts">
	import { function onDestroy(fn: () => any): void

Schedules a callback to run immediately before the component is unmounted.

Out of onMount, beforeUpdate, afterUpdate and onDestroy, this is the only one that runs inside a server-side component.

onDestroy
} from 'svelte';
function onDestroy(fn: () => any): void

Schedules a callback to run immediately before the component is unmounted.

Out of onMount, beforeUpdate, afterUpdate and onDestroy, this is the only one that runs inside a server-side component.

onDestroy
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component is being destroyed');
}); </script>
<script>
	import { function onDestroy(fn: () => any): void

Schedules a callback to run immediately before the component is unmounted.

Out of onMount, beforeUpdate, afterUpdate and onDestroy, this is the only one that runs inside a server-side component.

onDestroy
} from 'svelte';
function onDestroy(fn: () => any): void

Schedules a callback to run immediately before the component is unmounted.

Out of onMount, beforeUpdate, afterUpdate and onDestroy, this is the only one that runs inside a server-side component.

onDestroy
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component is being destroyed');
}); </script>

tick

While there’s no “after update” hook, you can use tick to ensure that the UI is updated before continuing. tick returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none.

<script lang="ts">
	import { function tick(): Promise<void>

Returns a promise that resolves once any pending state changes have been applied.

tick
} from 'svelte';
namespace $effect
function $effect(fn: () => void | (() => void)): void

Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is after the DOM has been updated.

Example:

$effect(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect Documentation}@paramfn The function to execute
$
namespace $effect
function $effect(fn: () => void | (() => void)): void

Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is after the DOM has been updated.

Example:

$effect(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect Documentation}@paramfn The function to execute
effect
.function $effect.pre(fn: () => void | (() => void)): void

Runs code right before a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is right before the DOM is updated.

Example:

$effect.pre(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.pre Documentation}@paramfn The function to execute
pre
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component is about to update');
function tick(): Promise<void>

Returns a promise that resolves once any pending state changes have been applied.

tick
().Promise<void>.then<void, never>(onfulfilled?: ((value: void) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of which ever callback is executed.
then
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component just updated');
}); }); </script>
<script>
	import { function tick(): Promise<void>

Returns a promise that resolves once any pending state changes have been applied.

tick
} from 'svelte';
namespace $effect
function $effect(fn: () => void | (() => void)): void

Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is after the DOM has been updated.

Example:

$effect(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect Documentation}@paramfn The function to execute
$
namespace $effect
function $effect(fn: () => void | (() => void)): void

Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is after the DOM has been updated.

Example:

$effect(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect Documentation}@paramfn The function to execute
effect
.function $effect.pre(fn: () => void | (() => void)): void

Runs code right before a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is right before the DOM is updated.

Example:

$effect.pre(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.pre Documentation}@paramfn The function to execute
pre
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component is about to update');
function tick(): Promise<void>

Returns a promise that resolves once any pending state changes have been applied.

tick
().Promise<void>.then<void, never>(onfulfilled?: ((value: void) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of which ever callback is executed.
then
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component just updated');
}); }); </script>

Deprecated: beforeUpdate / afterUpdate

Svelte 4 contained hooks that ran before and after the component as a whole was updated. For backwards compatibility, these hooks were shimmed in Svelte 5 but not available inside components that use runes.

<script lang="ts">
	import { function beforeUpdate(fn: () => void): void

Schedules a callback to run immediately before the component is updated after any state change.

The first time the callback runs will be before the initial onMount.

In runes mode use $effect.pre instead.

@deprecatedUse [`$effect.pre`](https://svelte.dev/docs/svelte/$effect#$effect.pre) instead
beforeUpdate
, function afterUpdate(fn: () => void): void

Schedules a callback to run immediately after the component has been updated.

The first time the callback runs will be after the initial onMount.

In runes mode use $effect instead.

@deprecatedUse [`$effect`](https://svelte.dev/docs/svelte/$effect) instead
afterUpdate
} from 'svelte';
function beforeUpdate(fn: () => void): void

Schedules a callback to run immediately before the component is updated after any state change.

The first time the callback runs will be before the initial onMount.

In runes mode use $effect.pre instead.

@deprecatedUse [`$effect.pre`](https://svelte.dev/docs/svelte/$effect#$effect.pre) instead
beforeUpdate
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component is about to update');
}); function afterUpdate(fn: () => void): void

Schedules a callback to run immediately after the component has been updated.

The first time the callback runs will be after the initial onMount.

In runes mode use $effect instead.

@deprecatedUse [`$effect`](https://svelte.dev/docs/svelte/$effect) instead
afterUpdate
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component just updated');
}); </script>
<script>
	import { function beforeUpdate(fn: () => void): void

Schedules a callback to run immediately before the component is updated after any state change.

The first time the callback runs will be before the initial onMount.

In runes mode use $effect.pre instead.

@deprecatedUse [`$effect.pre`](https://svelte.dev/docs/svelte/$effect#$effect.pre) instead
beforeUpdate
, function afterUpdate(fn: () => void): void

Schedules a callback to run immediately after the component has been updated.

The first time the callback runs will be after the initial onMount.

In runes mode use $effect instead.

@deprecatedUse [`$effect`](https://svelte.dev/docs/svelte/$effect) instead
afterUpdate
} from 'svelte';
function beforeUpdate(fn: () => void): void

Schedules a callback to run immediately before the component is updated after any state change.

The first time the callback runs will be before the initial onMount.

In runes mode use $effect.pre instead.

@deprecatedUse [`$effect.pre`](https://svelte.dev/docs/svelte/$effect#$effect.pre) instead
beforeUpdate
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component is about to update');
}); function afterUpdate(fn: () => void): void

Schedules a callback to run immediately after the component has been updated.

The first time the callback runs will be after the initial onMount.

In runes mode use $effect instead.

@deprecatedUse [`$effect`](https://svelte.dev/docs/svelte/$effect) instead
afterUpdate
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('the component just updated');
}); </script>

Instead of beforeUpdate use $effect.pre and instead of afterUpdate use $effect instead — these runes offer more granular control and only react to the changes you’re actually interested in.

Chat window example

To implement a chat window that autoscrolls to the bottom when new messages appear (but only if you were already scrolled to the bottom), we need to measure the DOM before we update it.

In Svelte 4, we do this with beforeUpdate, but this is a flawed approach — it fires before every update, whether it’s relevant or not. In the example below, we need to introduce checks like updatingMessages to make sure we don’t mess with the scroll position when someone toggles dark mode.

With runes, we can use $effect.pre, which behaves the same as $effect but runs before the DOM is updated. As long as we explicitly reference messages inside the effect body, it will run whenever messages changes, but not when theme changes.

beforeUpdate, and its equally troublesome counterpart afterUpdate, are therefore deprecated in Svelte 5.

<script lang="ts">
	import { beforeUpdate, afterUpdate, tick } from 'svelte';

	let updatingMessages = false;
	let theme = $state('dark');
	let messages = $state([]);

	let viewport;

	beforeUpdate(() => {
	$effect.pre(() => {
		if (!updatingMessages) return;
		messages;
		const autoscroll = viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50;

		if (autoscroll) {
			tick().then(() => {
				viewport.scrollTo(0, viewport.scrollHeight);
			});
		}

		updatingMessages = false;
	});

	function handleKeydown(event) {
		if (event.key === 'Enter') {
			const text = event.target.value;
			if (!text) return;

			updatingMessages = true;
			messages = [...messages, text];
			event.target.value = '';
		}
	}

	function toggle() {
		theme = theme === 'dark' ? 'light' : 'dark';
	}
</script>

<div class:dark={theme === 'dark'}>
	<div bind:this={viewport}>
		{#each messages as message}
			<p>{message}</p>
		{/each}
	</div>

	<input onkeydown={handleKeydown} />

	<button onclick={toggle}> Toggle dark mode </button>
</div>
<script>
	import { beforeUpdate, afterUpdate, tick } from 'svelte';

	let updatingMessages = false;
	let theme = $state('dark');
	let messages = $state([]);

	let viewport;

	beforeUpdate(() => {
	$effect.pre(() => {
		if (!updatingMessages) return;
		messages;
		const autoscroll = viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50;

		if (autoscroll) {
			tick().then(() => {
				viewport.scrollTo(0, viewport.scrollHeight);
			});
		}

		updatingMessages = false;
	});

	function handleKeydown(event) {
		if (event.key === 'Enter') {
			const text = event.target.value;
			if (!text) return;

			updatingMessages = true;
			messages = [...messages, text];
			event.target.value = '';
		}
	}

	function toggle() {
		theme = theme === 'dark' ? 'light' : 'dark';
	}
</script>

<div class:dark={theme === 'dark'}>
	<div bind:this={viewport}>
		{#each messages as message}
			<p>{message}</p>
		{/each}
	</div>

	<input onkeydown={handleKeydown} />

	<button onclick={toggle}> Toggle dark mode </button>
</div>