Svelte • Runes

$effect

On this page

Effects are functions that run when state updates, and can be used for things like calling third-party libraries, drawing on <canvas> elements, or making network requests. They only run in the browser, not during server-side rendering.

Generally speaking, you should not update state inside effects, as it will make code more convoluted and will often lead to never-ending update cycles. If you find yourself doing so, see when not to use $effect to learn about alternative approaches.

You can create an effect with the $effect rune (demo):

<script lang="ts">
	let size = $state(50);
	let color = $state('#ff3e00');

	let canvas;

	$effect(() => {
		const context = canvas.getContext('2d');
		context.clearRect(0, 0, canvas.width, canvas.height);

		// this will re-run whenever `color` or `size` change
		context.fillStyle = color;
		context.fillRect(0, 0, size, size);
	});
</script>

<canvas bind:this={canvas} width="100" height="100"></canvas>
<script>
	let size = $state(50);
	let color = $state('#ff3e00');

	let canvas;

	$effect(() => {
		const context = canvas.getContext('2d');
		context.clearRect(0, 0, canvas.width, canvas.height);

		// this will re-run whenever `color` or `size` change
		context.fillStyle = color;
		context.fillRect(0, 0, size, size);
	});
</script>

<canvas bind:this={canvas} width="100" height="100"></canvas>

When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside untrack), and re-runs the function when that state later changes.

If you’re having difficulty understanding why your $effect is rerunning or is not running see understanding dependencies. Effects are triggered differently than the $: blocks you may be used to if coming from Svelte 4.

Understanding lifecycle

Your effects run after the component has been mounted to the DOM, and in a microtask after state changes. Re-runs are batched (i.e. changing color and size in the same moment won’t cause two separate runs), and happen after any DOM updates have been applied.

You can use $effect anywhere, not just at the top level of a component, as long as it is called while a parent effect is running.

Svelte uses effects internally to represent logic and expressions in your template — this is how <h1>hello {name}!</h1> updates when name changes.

An effect can return a teardown function which will run immediately before the effect re-runs:

<script lang="ts">
	let let count: numbercount = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let milliseconds: numbermilliseconds =
function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(1000);
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
// This will be recreated whenever `milliseconds` changes const const interval: NodeJS.Timeoutinterval = function setInterval<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)setInterval(() => { let count: numbercount += 1; }, let milliseconds: numbermilliseconds); return () => { // if a teardown function is provided, it will run // a) immediately before the effect re-runs // b) when the component is destroyed function clearInterval(timeout: NodeJS.Timeout | string | number | undefined): void (+1 overload)clearInterval(const interval: NodeJS.Timeoutinterval); }; }); </script> <h1>{let count: numbercount}</h1> <button onclick={() => (let milliseconds: numbermilliseconds *= 2)}>slower</button> <button onclick={() => (let milliseconds: numbermilliseconds /= 2)}>faster</button>
<script>
	let let count: numbercount = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let milliseconds: numbermilliseconds =
function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(1000);
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
// This will be recreated whenever `milliseconds` changes const const interval: NodeJS.Timeoutinterval = function setInterval<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)setInterval(() => { let count: numbercount += 1; }, let milliseconds: numbermilliseconds); return () => { // if a teardown function is provided, it will run // a) immediately before the effect re-runs // b) when the component is destroyed function clearInterval(timeout: NodeJS.Timeout | string | number | undefined): void (+1 overload)clearInterval(const interval: NodeJS.Timeoutinterval); }; }); </script> <h1>{let count: numbercount}</h1> <button onclick={() => (let milliseconds: numbermilliseconds *= 2)}>slower</button> <button onclick={() => (let milliseconds: numbermilliseconds /= 2)}>faster</button>

Teardown functions also run when the effect is destroyed, which happens when its parent is destroyed (for example, a component is unmounted) or the parent effect re-runs.

Understanding dependencies

$effect automatically picks up any reactive values ($state, $derived, $props) that are synchronously read inside its function body (including indirectly, via function calls) and registers them as dependencies. When those dependencies change, the $effect schedules a re-run.

If $state and $derived are used directly inside the $effect (for example, during creation of a reactive class), those values will not be treated as dependencies.

Values that are read asynchronously — after an await or inside a setTimeout, for example — will not be tracked. Here, the canvas will be repainted when color changes, but not when size changes (demo):

// @filename: index.ts
declare let 
let canvas: {
    width: number;
    height: number;
    getContext(type: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D;
}
canvas
: {
width: numberwidth: number; height: numberheight: number; function getContext(type: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2DgetContext(type: "2d"type: '2d', options: CanvasRenderingContext2DSettings | undefinedoptions?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D; }; declare let let color: stringcolor: string; declare let let size: numbersize: number; // cut
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
const const context: CanvasRenderingContext2Dcontext =
let canvas: {
    width: number;
    height: number;
    getContext(type: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D;
}
canvas
.function getContext(type: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2DgetContext('2d');
const context: CanvasRenderingContext2Dcontext.CanvasRect.clearRect(x: number, y: number, w: number, h: number): voidclearRect(0, 0,
let canvas: {
    width: number;
    height: number;
    getContext(type: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D;
}
canvas
.width: numberwidth,
let canvas: {
    width: number;
    height: number;
    getContext(type: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D;
}
canvas
.height: numberheight);
// this will re-run whenever `color` changes... const context: CanvasRenderingContext2Dcontext.CanvasFillStrokeStyles.fillStyle: string | CanvasGradient | CanvasPatternfillStyle = let color: stringcolor; function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+1 overload)setTimeout(() => { // ...but not when `size` changes const context: CanvasRenderingContext2Dcontext.CanvasRect.fillRect(x: number, y: number, w: number, h: number): voidfillRect(0, 0, let size: numbersize, let size: numbersize); }, 0); });

An effect only reruns when the object it reads changes, not when a property inside it changes. (If you want to observe changes inside an object at dev time, you can use $inspect.)

<script lang="ts">
	let 
let state: {
    value: number;
}
state
=
function $state<{
    value: number;
}>(initial: {
    value: number;
}): {
    value: number;
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<{
    value: number;
}>(initial: {
    value: number;
}): {
    value: number;
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
({ value: numbervalue: 0 });
let
let derived: {
    value: number;
}
derived
=
function $derived<{
    value: number;
}>(expression: {
    value: number;
}): {
    value: number;
}
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
$
function $derived<{
    value: number;
}>(expression: {
    value: number;
}): {
    value: number;
}
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
derived
({ value: numbervalue:
let state: {
    value: number;
}
state
.value: numbervalue * 2 });
// this will run once, because `state` is never reassigned (only mutated)
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let state: {
    value: number;
}
state
;
}); // this will run whenever `state.value` changes...
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let state: {
    value: number;
}
state
.value: numbervalue;
}); // ...and so will this, because `derived` is a new object each time
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let derived: {
    value: number;
}
derived
;
}); </script> <button onclick={() => (
let state: {
    value: number;
}
state
.value: numbervalue += 1)}>
{
let state: {
    value: number;
}
state
.value: numbervalue}
</button> <p>{
let state: {
    value: number;
}
state
.value: numbervalue} doubled is {
let derived: {
    value: number;
}
derived
.value: numbervalue}</p>
<script>
	let 
let state: {
    value: number;
}
state
=
function $state<{
    value: number;
}>(initial: {
    value: number;
}): {
    value: number;
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<{
    value: number;
}>(initial: {
    value: number;
}): {
    value: number;
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
({ value: numbervalue: 0 });
let
let derived: {
    value: number;
}
derived
=
function $derived<{
    value: number;
}>(expression: {
    value: number;
}): {
    value: number;
}
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
$
function $derived<{
    value: number;
}>(expression: {
    value: number;
}): {
    value: number;
}
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
derived
({ value: numbervalue:
let state: {
    value: number;
}
state
.value: numbervalue * 2 });
// this will run once, because `state` is never reassigned (only mutated)
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let state: {
    value: number;
}
state
;
}); // this will run whenever `state.value` changes...
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let state: {
    value: number;
}
state
.value: numbervalue;
}); // ...and so will this, because `derived` is a new object each time
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let derived: {
    value: number;
}
derived
;
}); </script> <button onclick={() => (
let state: {
    value: number;
}
state
.value: numbervalue += 1)}>
{
let state: {
    value: number;
}
state
.value: numbervalue}
</button> <p>{
let state: {
    value: number;
}
state
.value: numbervalue} doubled is {
let derived: {
    value: number;
}
derived
.value: numbervalue}</p>

An effect only depends on the values that it read the last time it ran. This has interesting implications for effects that have conditional code.

For instance, if condition is true in the code snippet below, the code inside the if block will run and color will be evaluated. This means that changes to either condition or color will cause the effect to re-run.

Conversely, if condition is false, color will not be evaluated, and the effect will only re-run again when condition changes.

// @filename: ambient.d.ts
declare module 'canvas-confetti' {
	interface ConfettiOptions {
		ConfettiOptions.colors: string[]ConfettiOptions.colors: string[]colors: string[];
	}

	function function confetti(opts?: ConfettiOptions): voidfunction confetti(opts?: ConfettiOptions): voidconfetti(opts: ConfettiOptions | undefinedopts: ConfettiOptions | undefinedopts?: ConfettiOptions): void;
	export default function confetti(opts?: ConfettiOptions): voidfunction confetti(opts?: ConfettiOptions): voidconfetti;
}

// @filename: index.js
// cut
import function confetti(opts?: ConfettiOptions): voidfunction confetti(opts?: ConfettiOptions): voidconfetti from 'canvas-confetti';

let let condition: booleanlet condition: booleancondition = 
function $state<true>(initial: true): true (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
function $state<true>(initial: true): true (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$state
(true);
let let color: stringlet color: stringcolor =
function $state<"#ff3e00">(initial: "#ff3e00"): "#ff3e00" (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
function $state<"#ff3e00">(initial: "#ff3e00"): "#ff3e00" (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$state
('#ff3e00');
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
if (let condition: truelet condition: truecondition) { function confetti(opts?: ConfettiOptions): voidfunction confetti(opts?: ConfettiOptions): voidconfetti({ ConfettiOptions.colors: string[]ConfettiOptions.colors: string[]colors: [let color: stringlet color: stringcolor] }); } else { function confetti(opts?: ConfettiOptions): voidfunction confetti(opts?: ConfettiOptions): voidconfetti(); } });

$effect.pre

In rare cases, you may need to run code before the DOM updates. For this we can use the $effect.pre rune:

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

	let div = $state();
	let messages = $state([]);

	// ...

	$effect.pre(() => {
		if (!div) return; // not yet mounted

		// reference `messages` array length so that this code re-runs whenever it changes
		messages.length;

		// autoscroll when new messages are added
		if (div.offsetHeight + div.scrollTop > div.scrollHeight - 20) {
			tick().then(() => {
				div.scrollTo(0, div.scrollHeight);
			});
		}
	});
</script>

<div bind:this={div}>
	{#each messages as message}
		<p>{message}</p>
	{/each}
</div>
<script>
	import { tick } from 'svelte';

	let div = $state();
	let messages = $state([]);

	// ...

	$effect.pre(() => {
		if (!div) return; // not yet mounted

		// reference `messages` array length so that this code re-runs whenever it changes
		messages.length;

		// autoscroll when new messages are added
		if (div.offsetHeight + div.scrollTop > div.scrollHeight - 20) {
			tick().then(() => {
				div.scrollTo(0, div.scrollHeight);
			});
		}
	});
</script>

<div bind:this={div}>
	{#each messages as message}
		<p>{message}</p>
	{/each}
</div>

Apart from the timing, $effect.pre works exactly like $effect.

$effect.tracking

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template:

<script lang="ts">
	var console: Consoleconsole.Console.log(...data: any[]): void

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

MDN Reference

log
('in component setup:',
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.tracking(): boolean

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

Example:

<script>
  console.log('in component setup:', $effect.tracking()); // false

  $effect(() => {
    console.log('in effect:', $effect.tracking()); // true
  });
</script>

<p>in template: {$effect.tracking()}</p> <!-- true -->

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.tracking Documentation}
tracking
()); // false
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

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

MDN Reference

log
('in effect:',
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.tracking(): boolean

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

Example:

<script>
  console.log('in component setup:', $effect.tracking()); // false

  $effect(() => {
    console.log('in effect:', $effect.tracking()); // true
  });
</script>

<p>in template: {$effect.tracking()}</p> <!-- true -->

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.tracking Documentation}
tracking
()); // true
}); </script> <p>in template: {
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.tracking(): boolean

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

Example:

<script>
  console.log('in component setup:', $effect.tracking()); // false

  $effect(() => {
    console.log('in effect:', $effect.tracking()); // true
  });
</script>

<p>in template: {$effect.tracking()}</p> <!-- true -->

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.tracking Documentation}
tracking
()}</p> <!-- true -->
<script>
	var console: Consoleconsole.Console.log(...data: any[]): void

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

MDN Reference

log
('in component setup:',
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.tracking(): boolean

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

Example:

<script>
  console.log('in component setup:', $effect.tracking()); // false

  $effect(() => {
    console.log('in effect:', $effect.tracking()); // true
  });
</script>

<p>in template: {$effect.tracking()}</p> <!-- true -->

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.tracking Documentation}
tracking
()); // false
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
var console: Consoleconsole.Console.log(...data: any[]): void

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

MDN Reference

log
('in effect:',
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.tracking(): boolean

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

Example:

<script>
  console.log('in component setup:', $effect.tracking()); // false

  $effect(() => {
    console.log('in effect:', $effect.tracking()); // true
  });
</script>

<p>in template: {$effect.tracking()}</p> <!-- true -->

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.tracking Documentation}
tracking
()); // true
}); </script> <p>in template: {
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.tracking(): boolean

The $effect.tracking rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template.

Example:

<script>
  console.log('in component setup:', $effect.tracking()); // false

  $effect(() => {
    console.log('in effect:', $effect.tracking()); // true
  });
</script>

<p>in template: {$effect.tracking()}</p> <!-- true -->

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects.

@see{@link https://svelte.dev/docs/svelte/$effect#$effect.tracking Documentation}
tracking
()}</p> <!-- true -->

It is used to implement abstractions like createSubscriber, which will create listeners to update reactive values but only if those values are being tracked (rather than, for example, read inside an event handler).

$effect.pending

When using await in components, the $effect.pending() rune tells you how many promises are pending in the current boundary, not including child boundaries:

<script lang="ts">
	let a = $state(1);
	let b = $state(2);

	async function add(a, b) {
		await new Promise((f) => setTimeout(f, 500)); // artificial delay
		return a + b;
	}
</script>

<button onclick={() => a++}>a++</button>
<button onclick={() => b++}>b++</button>

<p>{a} + {b} = {await add(a, b)}</p>

{#if $effect.pending()}
	<p>pending promises: {$effect.pending()}</p>
{/if}
<script>
	let a = $state(1);
	let b = $state(2);

	async function add(a, b) {
		await new Promise((f) => setTimeout(f, 500)); // artificial delay
		return a + b;
	}
</script>

<button onclick={() => a++}>a++</button>
<button onclick={() => b++}>b++</button>

<p>{a} + {b} = {await add(a, b)}</p>

{#if $effect.pending()}
	<p>pending promises: {$effect.pending()}</p>
{/if}

$effect.root

The $effect.root rune is an advanced feature that creates a non-tracked scope that doesn’t auto-cleanup. This is useful for nested effects that you want to manually control. This rune also allows for the creation of effects outside of the component initialisation phase.

const const destroy: () => voidconst destroy: () => voiddestroy = 
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.root(fn: () => void | (() => void)): () => void

The $effect.root rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for nested effects that you want to manually control. This rune also allows for creation of effects outside of the component initialisation phase.

Example:

<script>
  let count = $state(0);

  const cleanup = $effect.root(() => {
    $effect(() => {
      console.log(count);
    })

    return () => {
      console.log('effect root cleanup');
    }
  });
</script>

<button onclick={() => cleanup()}>cleanup</button>
@see{@link https://svelte.dev/docs/svelte/$effect#$effect.root Documentation}
function $effect.root(fn: () => void | (() => void)): () => void

The $effect.root rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for nested effects that you want to manually control. This rune also allows for creation of effects outside of the component initialisation phase.

Example:

<script>
  let count = $state(0);

  const cleanup = $effect.root(() => {
    $effect(() => {
      console.log(count);
    })

    return () => {
      console.log('effect root cleanup');
    }
  });
</script>

<button onclick={() => cleanup()}>cleanup</button>
@see{@link https://svelte.dev/docs/svelte/$effect#$effect.root Documentation}
root
(() => {
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
// setup }); return () => { // cleanup }; }); // later... const destroy: () => voidconst destroy: () => voiddestroy();

When not to use $effect

In general, $effect is best considered something of an escape hatch — useful for things like analytics and direct DOM manipulation — rather than a tool you should use frequently. In particular, avoid using it to synchronise state. Instead of this…

<script lang="ts">
	let let count: numbercount = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let doubled: unknowndoubled =
function $state<unknown>(): unknown (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<unknown>(): unknown (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
();
// don't do this!
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let doubled: unknowndoubled = let count: numbercount * 2; }); </script>
<script>
	let let count: numbercount = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let doubled: unknowndoubled =
function $state<unknown>(): unknown (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<unknown>(): unknown (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
();
// don't do this!
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let doubled: unknowndoubled = let count: numbercount * 2; }); </script>

…do this:

<script lang="ts">
	let let count: numbercount = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let doubled: numberdoubled =
function $derived<number>(expression: number): number
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
$
function $derived<number>(expression: number): number
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
derived
(let count: numbercount * 2);
</script>
<script>
	let let count: numbercount = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let doubled: numberdoubled =
function $derived<number>(expression: number): number
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
$
function $derived<number>(expression: number): number
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}@paramexpression The derived state expression
derived
(let count: numbercount * 2);
</script>

For things that are more complicated than a simple expression like count * 2, you can also use $derived.by.

If you’re using an effect because you want to be able to reassign the derived value (to build an optimistic UI, for example) note that deriveds can be directly overridden as of Svelte 5.25.

You might be tempted to do something convoluted with effects to link one value to another. The following example shows two inputs for “money spent” and “money left” that are connected to each other. If you update one, the other should update accordingly. Instead of using effects for this…

<script lang="ts">
	const const total: 100total = 100;
	let let spent: numberspent = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let left: numberleft =
function $state<100>(initial: 100): 100 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<100>(initial: 100): 100 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(const total: 100total);
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let left: numberleft = const total: 100total - let spent: numberspent; });
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let spent: numberspent = const total: 100total - let left: numberleft; }); </script> <label> <input type="range" bind:value={let spent: numberspent} max={const total: 100total} /> {let spent: numberspent}/{const total: 100total} spent </label> <label> <input type="range" bind:value={let left: numberleft} max={const total: 100total} /> {let left: numberleft}/{const total: 100total} left </label> <style> label { display: flex; gap: 0.5em; } </style>
<script>
	const const total: 100total = 100;
	let let spent: numberspent = 
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<0>(initial: 0): 0 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(0);
let let left: numberleft =
function $state<100>(initial: 100): 100 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
$
function $state<100>(initial: 100): 100 (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}@paraminitial The initial value
state
(const total: 100total);
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let left: numberleft = const total: 100total - let spent: numberspent; });
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
$
function $effect(fn: () => void | (() => void)): void
namespace $effect

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
(() => {
let spent: numberspent = const total: 100total - let left: numberleft; }); </script> <label> <input type="range" bind:value={let spent: numberspent} max={const total: 100total} /> {let spent: numberspent}/{const total: 100total} spent </label> <label> <input type="range" bind:value={let left: numberleft} max={const total: 100total} /> {let left: numberleft}/{const total: 100total} left </label> <style> label { display: flex; gap: 0.5em; } </style>

…use oninput callbacks or — better still — function bindings where possible:

<script lang="ts">
	const total = 100;
	let spent = $state(0);
	let left = $derived(total - spent);

	function updateLeft(left) {
		spent = total - left;
	}
</script>

<label>
	<input type="range" bind:value={spent} max={total} />
	{spent}/{total} spent
</label>

<label>
	<input type="range" bind:value={() => left, updateLeft} max={total} />
	{left}/{total} left
</label>

<style>
	label {
		display: flex;
		gap: 0.5em;
	}
</style>
<script>
	const total = 100;
	let spent = $state(0);
	let left = $derived(total - spent);

	function updateLeft(left) {
		spent = total - left;
	}
</script>

<label>
	<input type="range" bind:value={spent} max={total} />
	{spent}/{total} spent
</label>

<label>
	<input type="range" bind:value={() => left, updateLeft} max={total} />
	{left}/{total} left
</label>

<style>
	label {
		display: flex;
		gap: 0.5em;
	}
</style>

If you absolutely have to update $state within an effect and run into an infinite loop because you read and write to the same $state, use untrack.