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
$effectis 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 whennamechanges.
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(0);
let let milliseconds: numbermilliseconds = function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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.
$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.
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(0);
let let milliseconds: numbermilliseconds = function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<1000>(initial: 1000): 1000 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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.
$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.
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.
$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);
$function $state<{
value: number;
}>(initial: {
value: number;
}): {
value: number;
} (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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);
$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);
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.
$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.
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.
$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.
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.
$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.
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);
$function $state<{
value: number;
}>(initial: {
value: number;
}): {
value: number;
} (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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);
$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);
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.
$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.
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.
$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.
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.
$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.
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);
function $state<true>(initial: true): true (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$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);
function $state<"#ff3e00">(initial: "#ff3e00"): "#ff3e00" (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$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.
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.
$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[]): voidThe console.log() static method outputs a message to the console.
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.
$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.tracking(): booleanThe $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.
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.
$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.
effect(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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.
$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.tracking(): booleanThe $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.
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.
$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.tracking(): booleanThe $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.
tracking()}</p> <!-- true --><script>
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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.
$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.tracking(): booleanThe $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.
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.
$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.
effect(() => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
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.
$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.tracking(): booleanThe $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.
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.
$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.tracking(): booleanThe $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.
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.
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.root(fn: () => void | (() => void)): () => voidThe $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>
function $effect.root(fn: () => void | (() => void)): () => voidThe $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>
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.
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.
$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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(0);
let let doubled: unknowndoubled = function $state<unknown>(): unknown (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<unknown>(): unknown (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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.
$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.
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(0);
let let doubled: unknowndoubled = function $state<unknown>(): unknown (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<unknown>(): unknown (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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.
$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.
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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);
$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);
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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);
$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);
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(0);
let let left: numberleft = function $state<100>(initial: 100): 100 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<100>(initial: 100): 100 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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.
$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.
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.
$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.
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);
$function $state<0>(initial: 0): 0 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
state(0);
let let left: numberleft = function $state<100>(initial: 100): 100 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$function $state<100>(initial: 100): 100 (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
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.
$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.
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.
$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.
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.