Svelte • Runtime
Lifecycle hooks
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)): voidonMount, 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>): voidonMount, 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[]): voidThe console.log() static method outputs a message to the console.
log('the component has mounted');
});
</script><script>
import { function onMount<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): voidonMount, 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>): voidonMount, 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[]): voidThe console.log() static method outputs a message to the console.
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)): voidonMount, 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>): voidonMount, 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[]): voidThe console.log() static method outputs a message to the console.
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)): voidonMount, 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>): voidonMount, 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[]): voidThe console.log() static method outputs a message to the console.
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
onMountis synchronous.asyncfunctions always return aPromise.
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): voidSchedules 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): voidSchedules 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[]): voidThe console.log() static method outputs a message to the console.
log('the component is being destroyed');
});
</script><script>
import { function onDestroy(fn: () => any): voidSchedules 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): voidSchedules 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[]): voidThe console.log() static method outputs a message to the console.
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.
$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.
effect.function $effect.pre(fn: () => void | (() => void)): voidRuns 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.
pre(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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.
then(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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.
$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.
effect.function $effect.pre(fn: () => void | (() => void)): voidRuns 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.
pre(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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.
then(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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): voidSchedules 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.
beforeUpdate, function afterUpdate(fn: () => void): voidSchedules 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.
afterUpdate } from 'svelte';
function beforeUpdate(fn: () => void): voidSchedules 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.
beforeUpdate(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
log('the component is about to update');
});
function afterUpdate(fn: () => void): voidSchedules 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.
afterUpdate(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
log('the component just updated');
});
</script><script>
import { function beforeUpdate(fn: () => void): voidSchedules 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.
beforeUpdate, function afterUpdate(fn: () => void): voidSchedules 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.
afterUpdate } from 'svelte';
function beforeUpdate(fn: () => void): voidSchedules 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.
beforeUpdate(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
log('the component is about to update');
});
function afterUpdate(fn: () => void): voidSchedules 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.
afterUpdate(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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>