We recommend using [SvelteKit](../kit), the official application framework from the Svelte team powered by [Vite](https://vite.dev/):
We recommend using [SvelteKit](../kit), which lets you [build almost anything](../kit/project-types). It's the official application framework from the Svelte team and powered by [Vite](https://vite.dev/). Create a new project with:
```bash
npx sv create myapp
@ -15,7 +15,9 @@ Don't worry if you don't know Svelte yet! You can ignore all the nice features S
## Alternatives to SvelteKit
You can also use Svelte directly with Vite by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory using [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you will probably need to [choose a routing library](faq#Is-there-a-router) as well.
You can also use Svelte directly with Vite by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS, and CSS files inside the `dist` directory using [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you will probably need to [choose a routing library](faq#Is-there-a-router) as well.
>[!NOTE] Vite is often used in standalone mode to build [single page apps (SPAs)](../kit/glossary#SPA), which you can also [build with SvelteKit](../kit/single-page-apps).
There are also plugins for [Rollup](https://github.com/sveltejs/rollup-plugin-svelte), [Webpack](https://github.com/sveltejs/svelte-loader) [and a few others](https://sveltesociety.dev/packages?category=build-plugins), but we recommend Vite.
@ -4,7 +4,7 @@ title: .svelte.js and .svelte.ts files
Besides `.svelte` files, Svelte also operates on `.svelte.js` and `.svelte.ts` files.
These behave like any other `.js` or `.ts` module, except that you can use runes. This is useful for creating reusable reactive logic, or sharing reactive state across your app.
These behave like any other `.js` or `.ts` module, except that you can use runes. This is useful for creating reusable reactive logic, or sharing reactive state across your app (though note that you [cannot export reassigned state]($state#Passing-state-across-modules)).
> [!LEGACY]
> This is a concept that didn't exist prior to Svelte 5
Svelte uses the `$props` rune to declare _properties_ or _props_, which means describing the public interface of the component which becomes accessible to consumers of the component.
> [!NOTE] `$props` is one of several runes, which are special hints for Svelte's compiler to make things reactive.
```svelte
<script>
let { foo, bar, baz } = $props();
// Values that are passed in as props
// are immediately available
console.log({ foo, bar, baz });
</script>
```
You can specify a fallback value for a prop. It will be used if the component's consumer doesn't specify the prop on the component when instantiating the component, or if the passed value is `undefined` at some point.
If you're using TypeScript, you can declare the prop types:
```svelte
<scriptlang="ts">
interface Props {
required: string;
optional?: number;
[key: string]: unknown;
}
let { required, optional, ...everythingElse }: Props = $props();
</script>
```
If you're using JavaScript, you can declare the prop types using JSDoc:
```svelte
<script>
/** @type {{ x: string }} */
let { x } = $props();
// or use @typedef if you want to document the properties:
/**
* @typedef {Object} MyProps
* @property {string} y Some documentation
*/
/** @type {MyProps} */
let { y } = $props();
</script>
```
If you export a `const`, `class` or `function`, it is readonly from outside the component.
```svelte
<script>
export const thisIs = 'readonly';
export function greet(name) {
alert(`hello ${name}!`);
}
</script>
```
Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](bindings#bind:this).
### Reactive variables
To change component state and trigger a re-render, just assign to a locally declared variable that was declared using the `$state` rune.
Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect.
```svelte
<script>
let count = $state(0);
function handleClick() {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
```
Svelte's `<script>` blocks are run only when the component is created, so assignments within a `<script>` block are not automatically run again when a prop updates.
```svelte
<script>
let { person } = $props();
// this will only set `name` on component creation
// it will not update when `person` does
let { name } = person;
</script>
```
If you'd like to react to changes to a prop, use the `$derived` or `$effect` runes instead.
```svelte
<script>
let count = $state(0);
let double = $derived(count * 2);
$effect(() => {
if (count > 10) {
alert('Too high!');
}
});
</script>
```
For more information on reactivity, read the documentation around runes.
Reactivity is at the heart of interactive UIs. When you click a button, you expect some kind of response. It's your job as a developer to make this happen. It's Svelte's job to make your job as intuitive as possible, by providing a good API to express reactive systems.
## Runes
Svelte 5 uses _runes_, a powerful set of primitives for controlling reactivity inside your Svelte components and inside `.svelte.js` and `.svelte.ts` modules.
Runes are function-like symbols that provide instructions to the Svelte compiler. You don't need to import them from anywhere — when you use Svelte, they're part of the language.
The following sections introduce the most important runes for declare state, derived state and side effects at a high level. For more details refer to the later sections on [state](state) and [side effects](side-effects).
## `$state`
Reactive state is declared with the `$state` rune:
```svelte
<script>
let count = $state(0);
</script>
<buttononclick={()=> count++}>
clicks: {count}
</button>
```
You can also use `$state` in class fields (whether public or private):
```js
// @errors: 7006 2554
class Todo {
done = $state(false);
text = $state();
constructor(text) {
this.text = text;
}
}
```
> [!LEGACY]
> In Svelte 4, state was implicitly reactive if the variable was declared at the top level
>
> ```svelte
> <script>
> let count = 0;
> </script>
>
> <buttonon:click={()=> count++}>
> clicks: {count}
> </button>
> ```
## `$derived`
Derived state is declared with the `$derived` rune:
```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<buttononclick={()=> count++}>
{doubled}
</button>
<p>{count} doubled is {doubled}</p>
```
The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions.
As with `$state`, you can mark class fields as `$derived`.
> [!LEGACY]
> In Svelte 4, you could use reactive statements for this.
>
> ```svelte
> <script>
> let count = 0;
> $: doubled = count * 2;
> </script>
>
> <buttonon:click={()=> count++}>
> {doubled}
> </button>
>
> <p>{count} doubled is {doubled}</p>
> ```
>
> This only worked at the top level of a component.
## `$effect`
To run _side-effects_ when the component is mounted to the DOM, and when values change, we can use the `$effect` rune ([demo](/playground/untitled#H4sIAAAAAAAAE31T24rbMBD9lUG7kAQ2sbdlX7xOYNk_aB_rQhRpbAsU2UiTW0P-vbrYubSlYGzmzMzROTPymdVKo2PFjzMzfIusYB99z14YnfoQuD1qQh-7bmdFQEonrOppVZmKNBI49QthCc-OOOH0LZ-9jxnR6c7eUpOnuv6KeT5JFdcqbvbcBcgDz1jXKGg6ncFyBedYR6IzLrAZwiN5vtSxaJA-EzadfJEjKw11C6GR22-BLH8B_wxdByWpvUYtqqal2XB6RVkG1CoHB6U1WJzbnYFDiwb3aGEdDa3Bm1oH12sQLTcNPp7r56m_00mHocSG97_zd7ICUXonA5fwKbPbkE2ZtMJGGVkEdctzQi4QzSwr9prnFYNk5hpmqVuqPQjNnfOJoMF22lUsrq_UfIN6lfSVyvQ7grB3X2mjMZYO3XO9w-U5iLx42qg29md3BP_ni5P4gy9ikTBlHxjLzAtPDlyYZmRdjAbGq7HprEQ7p64v4LU_guu0kvAkhBim3nMplWl8FreQD-CW20aZR0wq12t-KqDWeBywhvexKC3memmDwlHAv9q4Vo2ZK8KtK0CgX7u9J8wXbzdKv-nRnfF_2baTqlYoWUF2h5efl9-n0O6koAMAAA==)):
The function passed to `$effect` will run when the component mounts, and will re-run after any changes to the values it reads that were declared with `$state` or `$derived` (including those passed in with `$props`). 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.
> [!LEGACY]
> In Svelte 4, you could use reactive statements for this.
...though if you find yourself writing code like that, consider using [classes](#Classes) instead.
## Passing state across modules
You can declare state in `.svelte.js` and `.svelte.ts` files, but you can only _export_ that state if it's not directly reassigned. In other words you can't do this:
```js
/// file: state.svelte.js
export let count = $state(0);
export function increment() {
count += 1;
}
```
That's because every reference to `count` is transformed by the Svelte compiler — the code above is roughly equivalent to this:
```js
/// file: state.svelte.js (compiler output)
// @filename: index.ts
interface Signal<T> {
value: T;
}
interface Svelte {
state<T>(value?: T): Signal<T>;
get<T>(source: Signal<T>): T;
set<T>(source: Signal<T>, value: T): void;
}
declare const $: Svelte;
// ---cut---
export let count = $.state(0);
export function increment() {
$.set(count, $.get(count) + 1);
}
```
> [!NOTE] You can see the code Svelte generates by clicking the 'JS Output' tab in the [playground](/playground).
Since the compiler only operates on one file at a time, if another file imports `count` Svelte doesn't know that it needs to wrap each reference in `$.get` and `$.set`:
```js
// @filename: state.svelte.js
export let count = 0;
// @filename: index.js
// ---cut---
import { count } from './state.svelte.js';
console.log(typeof count); // 'object', not 'number'
```
This leaves you with two options for sharing state between modules — either don't reassign it...
@ -52,6 +52,48 @@ Anything read synchronously inside the `$derived` expression (or `$derived.by` f
To exempt a piece of state from being treated as a dependency, use [`untrack`](svelte#untrack).
## Overriding derived values
Derived expressions are recalculated when their dependencies change, but you can temporarily override their values by reassigning them (unless they are declared with `const`). This can be useful for things like _optimistic UI_, where a value is derived from the 'source of truth' (such as data from your server) but you'd like to show immediate feedback to the user:
```svelte
<script>
let { post, like } = $props();
let likes = $derived(post.likes);
async function onclick() {
// increment the `likes` count immediately...
likes += 1;
// and tell the server, which will eventually update `post`
try {
await like();
} catch {
// failed! roll back the change
likes -= 1;
}
}
</script>
<button{onclick}>🧡 {likes}</button>
```
> [!NOTE] Prior to Svelte 5.25, deriveds were read-only.
## Deriveds and reactivity
Unlike `$state`, which converts objects and arrays to [deeply reactive proxies]($state#Deep-state), `$derived` values are left as-is. For example, [in a case like this](/playground/untitled#H4sIAAAAAAAAE4VU22rjMBD9lUHd3aaQi9PdstS1A3t5XvpQ2Ic4D7I1iUUV2UjjNMX431eS7TRdSosxgjMzZ45mjt0yzffIYibvy0ojFJWqDKCQVBk2ZVup0LJ43TJ6rn2aBxw-FP2o67k9oCKP5dziW3hRaUJNjoYltjCyplWmM1JIIAn3FlL4ZIkTTtYez6jtj4w8WwyXv9GiIXiQxLVs9pfTMR7EuoSLIuLFbX7Z4930bZo_nBrD1bs834tlfvsBz9_SyX6PZXu9XaL4gOWn4sXjeyzftv4ZWfyxubpzxzg6LfD4MrooxELEosKCUPigQCMPKCZh0OtQE1iSxcsmdHuBvCiHZXALLXiN08EL3RRkaJ_kDVGle0HcSD5TPEeVtj67O4Nrg9aiSNtBY5oODJkrL5QsHtN2cgXp6nSJMWzpWWGasdlsGEMbzi5jPr5KFr0Ep7pdeM2-TCelCddIhDxAobi1jqF3cMaC1RKp64bAW9iFAmXGIHfd4wNXDabtOLN53w8W53VvJoZLh7xk4Rr3CoL-UNoLhWHrT1JQGcM17u96oES5K-kc2XOzkzqGCKL5De79OUTyyrg1zgwXsrEx3ESfx4Bz0M5UjVMHB24mw9SuXtXFoN13fYKOM1tyUT3FbvbWmSWCZX2Er-41u5xPoml45svRahl9Wb9aasbINJixDZwcPTbyTLZSUsAvrg_cPuCR7s782_WU8343Y72Qtlb8OYatwuOQvuN13M_hJKNfxann1v1U_B1KZ_D_mzhzhz24fw85CSz2irtN9w9HshBK7AQAAA==)...
```svelte
let items = $state([...]);
let index = $state(0);
let selected = $derived(items[index]);
```
...you can change (or `bind:` to) properties of `selected` and it will affect the underlying `items` array. If `items` was _not_ deeply reactive, mutating `selected` would have no effect.
## Update propagation
Svelte uses something called _push-pull reactivity_ — when state is updated, everything that depends on the state (whether directly or indirectly) is immediately notified of the change (the 'push'), but derived values are not re-evaluated until they are actually read (the 'pull').
Effects are what make your application _do things_. When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside [`untrack`](svelte#untrack)), and re-runs the function when that state later changes.
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.
Most of the effects in a Svelte app are created by Svelte itself — they're the bits that update the text in `<h1>hello {name}!</h1>` when `name` changes, for example.
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`](#When-not-to-use-$effect) to learn about alternative approaches.
But you can also create your own effects with the `$effect` rune, which is useful when you need to synchronize an external system (whether that's a library, or a `<canvas>` element, or something across a network) with state inside your Svelte app.
> [!NOTE] Avoid overusing `$effect`! When you do too much work in effects, code often becomes difficult to understand and maintain. See [when not to use `$effect`](#When-not-to-use-$effect) to learn about alternative approaches.
Your effects run after the component has been mounted to the DOM, and in a [microtask](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) after state changes ([demo](/playground/untitled#H4sIAAAAAAAAE31S246bMBD9lZF3pSRSAqTVvrCAVPUP2sdSKY4ZwJJjkD0hSVH-vbINuWxXfQH5zMyZc2ZmZLVUaFn6a2R06ZGlHmBrpvnBvb71fWQHVOSwPbf4GS46TajJspRlVhjZU1HqkhQSWPkHIYdXS5xw-Zas3ueI6FRn7qHFS11_xSRZhIxbFtcDtw7SJb1iXaOg5XIFeQGjzyPRaevYNOGZIJ8qogbpe8CWiy_VzEpTXiQUcvPDkSVrSNZz1UlW1N5eLcqmpdXUvaQ4BmqlhZNUCgxuzFHDqUWNAxrYeUM76AzsnOsdiJbrBp_71lKpn3RRbii-4P3f-IMsRxS-wcDV_bL4PmSdBa2wl7pKnbp8DMgVvJm8ZNskKRkEM_OzyOKQFkgqOYBQ3Nq89Ns0nbIl81vMFN-jKoLMTOr-SOBOJS-Z8f5Y6D1wdcR8dFqvEBdetK-PHwj-z-cH8oHPY54wRJ8Ys7iSQ3Bg3VA9azQbmC9k35kKzYa6PoVtfwbbKVnBixBiGn7Pq0rqJoUtHiCZwAM3jdTPWCVtr_glhVrhecIa3vuksJ_b7TqFs4DPyriSjd5IwoNNQaAmNI-ESfR2p8zimzvN1swdCkvJHPH6-_oX8o1SgcIDAAA=)):
You can create an effect with the `$effect` rune ([demo](/playground/untitled#H4sIAAAAAAAAE31S246bMBD9lZF3pSRSAqTVvrCAVPUP2sdSKY4ZwJJjkD0hSVH-vbINuWxXfQH5zMyZc2ZmZLVUaFn6a2R06ZGlHmBrpvnBvb71fWQHVOSwPbf4GS46TajJspRlVhjZU1HqkhQSWPkHIYdXS5xw-Zas3ueI6FRn7qHFS11_xSRZhIxbFtcDtw7SJb1iXaOg5XIFeQGjzyPRaevYNOGZIJ8qogbpe8CWiy_VzEpTXiQUcvPDkSVrSNZz1UlW1N5eLcqmpdXUvaQ4BmqlhZNUCgxuzFHDqUWNAxrYeUM76AzsnOsdiJbrBp_71lKpn3RRbii-4P3f-IMsRxS-wcDV_bL4PmSdBa2wl7pKnbp8DMgVvJm8ZNskKRkEM_OzyOKQFkgqOYBQ3Nq89Ns0nbIl81vMFN-jKoLMTOr-SOBOJS-Z8f5Y6D1wdcR8dFqvEBdetK-PHwj-z-cH8oHPY54wRJ8Ys7iSQ3Bg3VA9azQbmC9k35kKzYa6PoVtfwbbKVnBixBiGn7Pq0rqJoUtHiCZwAM3jdTPWCVtr_glhVrhecIa3vuksJ_b7TqFs4DPyriSjd5IwoNNQaAmNI-ESfR2p8zimzvN1swdCkvJHPH6-_oX8o1SgcIDAAA=)):
```svelte
<script>
@ -29,14 +25,22 @@ Your effects run after the component has been mounted to the DOM, and in a [micr
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.
When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside [`untrack`](svelte#untrack)), and re-runs the function when that state later changes.
> [!NOTE] If you're having difficulty understanding why your `$effect` is rerunning or is not running see [understanding dependencies](#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](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) 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.
You can place `$effect` anywhere, not just at the top level of a component, as long as it is called during component initialization (or while a parent effect is active). It is then tied to the lifecycle of the component (or parent effect) and will therefore destroy itself when the component unmounts (or the parent effect is destroyed).
> [!NOTE] Svelte uses effects internally to represent logic and expressions in your template —this is how `<h1>hello {name}!</h1>` updates when `name` changes.
You can return a function from `$effect`, which will run immediately before the effect re-runs, and before it is destroyed ([demo](/playground/untitled#H4sIAAAAAAAAE42RQY-bMBCF_8rI2kPopiXpMQtIPfbeW6m0xjyKtWaM7CFphPjvFVB2k2oPe7LmzXzyezOjaqxDVKefo5JrD3VaBLVXrLu5-tb3X-IZTmat0hHv6cazgCWqk8qiCbaXouRSHISMH1gop4coWrA7JE9bp7PO2QjjuY5vA8fDYZ3hUh7QNDCy2yWUFzTOUilpSj9aG-linaMKFGACtKCmSwvGGYGeLQvCWbtnMq3m34grajxHoa1JOUXI93_V_Sfz7Oz7Mafj0ypN-zvHm8dSAmQITP_xaUq2IU1GO1dp80I2Uh_82dao92Rl9R8GvgF0QrbrUFstcFeq0PgAkha0LoICPoeB4w1SJUvsZcj4rvcMlvmvGlGCv6J-DeSgw2vabQnJlm55p7nM0rcTctYei3HZxZSl7XHVqkHEM3k2zpqXfFyj393zU05fpyI6f0HI0hUoPoamC9roKDeo2ivBH1EnCQOmX9NfYw2GHrgCAAA=)).
An effect can return a _teardown function_ which will run immediately before the effect re-runs ([demo](/playground/untitled#H4sIAAAAAAAAE42SQVODMBCF_8pOxkPRKq3HCsx49K4n64xpskjGkDDJ0tph-O8uINo6HjxB3u7HvrehE07WKDbiyZEhi1osRWksRrF57gQdm6E2CKx_dd43zU3co6VB28mIf-nKO0JH_BmRRRVMQ8XWbXkAgfKtI8jhIpIkXKySu7lSG2tNRGZ1_GlYr1ZTD3ddYFmiosUigbyAbpC2lKbwWJkIB8ZhhxBQBWRSw6FCh3sM8GrYTthL-wqqku4N44TyqEgwF3lmRHr4Op0PGXoH31c5rO8mqV-eOZ49bikgtcHBL55tmhIkEMqg_cFB2TpFxjtg703we6NRL8HQFCS07oSUCZi6Rm04lz1yytIHBKoQpo1w6Gsm4gmyS8b8Y5PydeMdX8gwS2Ok4I-ov5NZtvQde95GMsccn_1wzNKfu3RZtS66cSl9lvL7qO1aIk7knbJGvefdtIOzi73M4bYvovUHDFk6AcX_0HRESxnpBOW_jfCDxIZCi_1L_wm4xGQ60wIAAA==)).
```svelte
<script>
@ -50,7 +54,7 @@ You can return a function from `$effect`, which will run immediately before the
}, milliseconds);
return () => {
// if a callback is provided, it will run
// if a teardown function is provided, it will run
// a) immediately before the effect re-runs
// b) when the component is destroyed
clearInterval(interval);
@ -64,9 +68,13 @@ You can return a function from `$effect`, which will run immediately before the
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 rerun.
`$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](https://svelte.dev/docs/svelte/$state#Classes)), 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](/playground/untitled#H4sIAAAAAAAAE31T246bMBD9lZF3pWSlBEirfaEQqdo_2PatVIpjBrDkGGQPJGnEv1e2IZfVal-wfHzmzJyZ4cIqqdCy9M-F0blDlnqArZjmB3f72XWRHVCRw_bc4me4aDWhJstSlllhZEfbQhekkMDKfwg5PFvihMvX5OXH_CJa1Zrb0-Kpqr5jkiwC48rieuDWQbqgZ6wqFLRcvkC-hYvnkWi1dWqa8ESQTxFRjfQWsOXiWzmr0sSLhEJu3p1YsoJkNUcdZUnN9dagrBu6FVRQHAM10sJRKgUG16bXcGxQ44AGdt7SDkTDdY02iqLHnJVU6hedlWuIp94JW6Tf8oBt_8GdTxlF0b4n0C35ZLBzXb3mmYn3ae6cOW74zj0YVzDNYXRHFt9mprNgHfZSl6mzml8CMoLvTV6wTZIUDEJv5us2iwMtiJRyAKG4tXnhl8O0yhbML0Wm-B7VNlSSSd31BG7z8oIZZ6dgIffAVY_5xdU9Qrz1Bnx8fCfwtZ7v8Qc9j3nB8PqgmMWlHIID6-bkVaPZwDySfWtKNGtquxQ23Qlsq2QJT0KIqb8dL0up6xQ2eIBkAg_c1FI_YqW0neLnFCqFpwmreedJYT7XX8FVOBfwWRhXstZrSXiwKQjUhOZeMIleb5JZfHWn2Yq5pWEpmR7Hv-N_wEqT8hEEAAA=)):
@ -127,19 +135,33 @@ An effect only reruns when the object it reads changes, not when a property insi
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 `a` is `true` in the code snippet below, the code inside the `if` block will run and `b` will be evaluated. As such, changes to either `a` or `b` [will cause the effect to re-run](/playground/untitled#H4sIAAAAAAAAE3VQzWrDMAx-FdUU4kBp71li6EPstOxge0ox8-QQK2PD-N1nLy2F0Z2Evj9_chKkP1B04pnYscc3cRCT8xhF95IEf8-Vq0DBr8rzPB_jJ3qumNERH-E2ECNxiRF9tIubWY00lgcYNAywj6wZJS8rtk83wjwgCrXHaULLUrYwKEgVGrnkx-Dx6MNFNstK5OjSbFGbwE0gdXuT_zGYrjmAuco515Hr1p_uXak3K3MgCGS9s-9D2grU-judlQYXIencnzad-tdR79qZrMyvw9wd5Z8Yv1h09dz8mn8AkM7Pfo0BAAA=).
For instance, if `condition` is `true` in the code snippet below, the code inside the `if` block will run and `color` will be evaluated. As such, changes to either `condition` or `color` [will cause the effect to re-run](/playground/untitled#H4sIAAAAAAAAE21RQW6DMBD8ytaNBJHaJFLViwNIVZ8RcnBgXVk1xsILTYT4e20TQg89IOPZ2fHM7siMaJBx9tmaWpFqjQNlAKXEihx7YVJpdIyfRkY3G4gB8Pi97cPanRtQU8AuwuF_eNUaQuPlOMtc1SlLRWlKUo1tOwJflUikQHZtA0klzCDc64Imx0ANn8bInV1CDhtHgjClrsftcSXotluLybOUb3g4JJHhOZs5WZpuIS9gjNqkJKQP5e2ClrR4SMdZ13E4xZ8zTPOTJU2A2uE_PQ9COCI926_hTVarIU4hu_REPlBrKq2q73ycrf1N-vS4TMUsulaVg3EtR8H9rFgsg8uUsT1B2F9eshigZHBRpuaD0D3mY8Qm2BfB5N2YyRzdNEYVDy0Ja-WsFjcOUuP1HvFLWA6H3XuHTUSmmDV2--0TXonxsKbp7G9C6R__NONS-MFNvxj_d6mBAgAA).
Conversely, if `a` is `false`, `b` will not be evaluated, and the effect will _only_ re-run when `a` changes.
Conversely, if `condition` is `false`, `color` will not be evaluated, and the effect will _only_ re-run again when `condition` changes.
```ts
let a = false;
let b = false;
// @filename: ambient.d.ts
declare module 'canvas-confetti' {
interface ConfettiOptions {
colors: string[];
}
function confetti(opts?: ConfettiOptions): void;
export default confetti;
}
// @filename: index.js
// ---cut---
$effect(() => {
console.log('running');
import confetti from 'canvas-confetti';
if (a) {
console.log('b:', b);
let condition = $state(true);
let color = $state('#ff3e00');
$effect(() => {
if (condition) {
confetti({ colors: [color] });
} else {
confetti();
}
});
```
@ -203,20 +225,19 @@ It is used to implement abstractions like [`createSubscriber`](/docs/svelte/svel
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.
```svelte
<script>
let count = $state(0);
```js
const destroy = $effect.root(() => {
$effect(() => {
// setup
});
const cleanup = $effect.root(() => {
$effect(() => {
console.log(count);
});
return () => {
// cleanup
};
});
return () => {
console.log('effect root cleanup');
};
});
</script>
// later...
destroy();
```
## When not to use `$effect`
@ -246,6 +267,8 @@ In general, `$effect` is best considered something of an escape hatch — useful
> [!NOTE] 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]($derived#Overriding-derived-values) 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. Don't use effects for this ([demo](/playground/untitled#H4sIAAAAAAAACpVRy26DMBD8FcvKgUhtoIdeHBwp31F6MGSJkBbHwksEQvx77aWQqooq9bgzOzP7mGTdIHipPiZJowOpGJAv0po2VmfnDv4OSBErjYdneHWzBJaCjcx91TWOToUtCIEE3cig0OIty44r5l1oDtjOkyFIsv3GINQ_CNYyGegd1DVUlCR7oU9iilDUcP8S8roYs9n8p2wdYNVFm4csTx872BxNCcjr5I11fdgonEkXsjP2CoUUZWMv6m6wBz2x7yxaM-iJvWeRsvSbSVeUy5i0uf8vKA78NIeJLSZWv1I8jQjLdyK4XuTSeIdmVKJGGI4LdjVOiezwDu1yG74My8PLCQaSiroe5s_5C2PHrkVGAgAA)):
```svelte
@ -274,7 +297,7 @@ You might be tempted to do something convoluted with effects to link one value t
</label>
```
Instead, use callbacks where possible ([demo](/playground/untitled#H4sIAAAAAAAACo1SMW6EMBD8imWluFMSIEUaDiKlvy5lSOHjlhOSMRZeTiDkv8deMEEJRcqdmZ1ZjzzxqpZgePo5cRw18JQA_sSVaPz0rnVk7iDRYxdhYA8vW4Wg0NnwzJRdrfGtUAVKQIYtCsly9pIkp4AZ7cQOezAoEA7JcWUkVBuCdol0dNWrEutWsV5fHfnhPQ5wZJMnCwyejxCh6G6A0V3IHk4zu_jOxzzPBxBld83PTr7xXrb3rUNw8PbiYJ3FP22oTIoLSComq5XuXTeu8LzgnVA3KDgj13wiQ8taRaJ82rzXskYM-URRlsXktejjgNLoo9e4fyf70_8EnwncySX1GuunX6kGRwnzR_BgaPNaGy3FmLJKwrCUeBM6ZUn0Cs2mOlp3vwthQJ5i14P9st9vZqQlsQIAAA==)):
Instead, use `oninput`callbacks or — better still — [function bindings](bind#Function-bindings) where possible ([demo](/playground/untitled#H4sIAAAAAAAAE51SsW6DMBT8FcvqABINdOhCIFKXTt06lg4GHpElYyz8iECIf69tcIIipo6-u3f3fPZMJWuBpvRzkBXyTpKSy5rLq6YRbbgATdOfmeKkrMgCBt9GPpQ66RsItFjJNBzhVScRJBobmumq5wovhSxQABLskAmSk7ckOXtMKyM22ItGhhAk4Z0R0OwIN-tIQzd-90HVhvy2HsGNiQFCMltBgd7XoecV2xzXNV7XaEcth7ZfRv7kujnsTX2Qd7USb5rFjwZkJlgJwpWRcakG04cpOS9oz-QVCuoeInXW-RyEJL-sG0b7Wy6kZWM-u7CFxM5tdrIl9qg72vB74H-y7T2iXROHyVb0CLanp1yNk4D1A1jQ91hzrQSbUtIIGLcir0ylJDm9Q7urz42bX4UwIk2xH2D5Xf4A7SeMcMQCAAA=)):
```svelte
<script>
@ -282,54 +305,26 @@ Instead, use callbacks where possible ([demo](/playground/untitled#H4sIAAAAAAAAC
If you need to use bindings, for whatever reason (for example when you want some kind of "writable `$derived`"), consider using getters and setters to synchronise state ([demo](/playground/untitled#H4sIAAAAAAAACpWRwW6DMBBEf8WyekikFOihFwcq9TvqHkyyQUjGsfCCQMj_XnvBNKpy6Qn2DTOD1wu_tRocF18Lx9kCFwT4iRvVxenT2syNoDGyWjl4xi93g2AwxPDSXfrW4oc0EjUgwzsqzSr2VhTnxJwNHwf24lAhHIpjVDZNwy1KS5wlNoGMSg9wOCYksQccerMlv65p51X0p_Xpdt_4YEy9yTkmV3z4MJT579-bUqsaNB2kbI0dwlnCgirJe2UakJzVrbkKaqkWivasU1O1ULxnOVk3JU-Uxti0p_-vKO4no_enbQ_yXhnZn0aHs4b1jiJMK7q2zmo1C3bTMG3LaZQVrMjeoSPgaUtkDxePMCEX2Ie6b_8D4WyJJEwCAAA=)):
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](svelte#untrack).
When compiling a component as a custom element, the `$host` rune provides access to the host element, allowing you to (for example) dispatch custom events ([demo](/playground/untitled#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-Bx_ABXQWmOtAgAA)):
When compiling a component as a [custom element](custom-elements), the `$host` rune provides access to the host element, allowing you to (for example) dispatch custom events ([demo](/playground/untitled#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-Bx_ABXQWmOtAgAA)):
@ -154,6 +154,8 @@ A JavaScript expression can be included as text by surrounding it with curly bra
{expression}
```
Expressions that are `null` or `undefined` will be omitted; all others are [coerced to strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion).
Curly braces can be included in a Svelte template by using their [HTML entity](https://developer.mozilla.org/docs/Glossary/Entity) strings: `{`, `{`, or `{` for `{` and `}`, `}`, or `}` for `}`.
If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses.
@ -185,7 +187,7 @@ You can use HTML comments inside components.
Comments beginning with `svelte-ignore` disable warnings for the next block of markup. Usually, these are accessibility warnings; make sure that you're disabling them for a good reason.
@ -112,6 +112,8 @@ Snippets can reference themselves and each other ([demo](/playground/untitled#H4
## Passing snippets to components
### Explicit props
Within the template, snippets are values just like any other. As such, they can be passed to components as props ([demo](/playground/untitled#H4sIAAAAAAAAE3VS247aMBD9lZGpBGwDASRegonaPvQL2qdlH5zYEKvBNvbQLbL875VzAcKyj3PmzJnLGU8UOwqSkd8KJdaCk4TsZS0cyV49wYuJuQiQpGd-N2bu_ooaI1YwJ57hpVYoFDqSEepKKw3mO7VDeTTaIvxiRS1gb_URxvO0ibrS8WanIrHUyiHs7Vmigy28RmyHHmKvDMbMmFq4cQInvGSwTsBYWYoMVhCSB2rBFFPsyl0uruTlR3JZCWvlTXl1Yy_mawiR_rbZKZrellJ-5JQ0RiBUgnFhJ9OGR7HKmwVoilXeIye8DOJGfYCgRlZ3iE876TBsZPX7hPdteO75PC4QaIo8vwNPePmANQ2fMeEFHrLD7rR1jTNkW986E8C3KwfwVr8HSHOSEBT_kGRozyIkn_zQveXDL3rIfPJHtUDwzShJd_Qk3gQCbOGLsdq4yfTRJopRuin3I7nv6kL7ARRjmLdBDG3uv1mhuLA3V2mKtqNEf_oCn8p9aN-WYqH5peP4kWBl1UwJzAEPT9U7K--0fRrrWnPTXpCm1_EVdXjpNmlA8G1hPPyM1fKgMqjFHjctXGjLhZ05w0qpDhksGrybuNEHtJnCalZWsuaTlfq6nPaaBSv_HKw-K57BjzOiVj9ZKQYKzQjZodYFqydYTRN4gPhVzTDO2xnma3HsVWjaLjT8nbfwHy7Q5f2dBAAA)):
```svelte
@ -144,6 +146,8 @@ Within the template, snippets are values just like any other. As such, they can
Think about it like passing content instead of data to a component. The concept is similar to slots in web components.
### Implicit props
As an authoring convenience, snippets declared directly _inside_ a component implicitly become props _on_ the component ([demo](/playground/untitled#H4sIAAAAAAAAE3VSTa_aMBD8Kyu_SkAbCA-JSzBR20N_QXt6vIMTO8SqsY29tI2s_PcqTiB8vaPHs7MzuxuIZgdBMvJLo0QlOElIJZXwJHsLBBvb_XUASc7Mb9Yu_B-hsMMK5sUzvDQahUZPMkJ96aTFfKd3KA_WOISfrFACKmcOMFmk8TWUTjY73RFLoz1C5U4SPWzhrcN2GKDrlcGEWauEnyRwxCaDdQLWyVJksII2uaMWTDPNLtzX5YX8-kgua-GcHJVXI3u5WEPb0d83O03TMZSmfRzOkG1Db7mNacOL19JagVALxoWbztq-H8U6j0SaYp2P2BGbOyQ2v8PQIFMXLKRDk177pq0zf6d8bMrzwBdd0pamyPMb-IjNEzS2f86Gz_Dwf-2F9nvNSUJQ_EOSoTuJNvngqK5v4Pas7n4-OCwlEEJcQTIMO-nSQwtb-GSdsX46e9gbRoP9yGQ11I0rEuycunu6PHx1QnPhxm3SFN15MOlYEFJZtf0dUywMbwZOeBGsrKNLYB54-1R9WNqVdki7usim6VmQphf7mnpshiQRhNAXdoOfMyX3OgMlKtz0cGEcF27uLSul3mewjPjgOOoDukxjPS9rqfh0pb-8zs6aBSt_7505aZ7B9xOi0T9YKW4UooVsr0zB1BTrWQJ3EL-oWcZ572GxFoezCk37QLe3897-B2i2U62uBAAA)):
```svelte
@ -165,6 +169,8 @@ As an authoring convenience, snippets declared directly _inside_ a component imp
</Table>
```
### Implicit `children` snippet
Any content inside the component tags that is _not_ a snippet declaration implicitly becomes part of the `children` snippet ([demo](/playground/untitled#H4sIAAAAAAAAE3WOQQrCMBBFrzIMggql3ddY1Du4si5sOmIwnYRkFKX07lKqglqX8_7_w2uRDw1hjlsWI5ZqTPBoLEXMdy3K3fdZDzB5Ndfep_FKVnpWHSKNce1YiCVijirqYLwUJQOYxrsgsLmIOIZjcA1M02w4n-PpomSVvTclqyEutDX6DA2pZ7_ABIVugrmEC3XJH92P55_G39GodCmWBFrQJ2PrQAwdLGHig_NxNv9xrQa1dhWIawrv1Wzeqawa8953D-8QOmaEAQAA)):
```svelte
@ -184,6 +190,8 @@ Any content inside the component tags that is _not_ a snippet declaration implic
> [!NOTE] Note that you cannot have a prop called `children` if you also have content inside the component — for this reason, you should avoid having props with that name
### Optional snippet props
You can declare snippet props as being optional. You can either use optional chaining to not render anything if the snippet isn't set...
@ -22,10 +22,6 @@ The `transition:` directive indicates a _bidirectional_ transition, which means
{/if}
```
## Built-in transitions
A selection of built-in transitions can be imported from the [`svelte/transition`](svelte-transition) module.
## Local vs global
Transitions are local by default. Local transitions only play when the block they belong to is created or destroyed, _not_ when parent blocks are created or destroyed.
@ -40,6 +36,10 @@ Transitions are local by default. Local transitions only play when the block the
{/if}
```
## Built-in transitions
A selection of built-in transitions can be imported from the [`svelte/transition`](svelte-transition) module.
- await (or move that into some kind of data loading section?)
- NOT: key (move into transition section, because that's the common use case)
Svelte augments HTML with control flow blocks to be able to express conditionally rendered content or lists.
The syntax between these blocks is the same:
- `{#` denotes the start of a block
- `{:` denotes a different branch part of the block. Depending on the block, there can be multiple of these
- `{/` denotes the end of a block
## {#if ...}
## {#each ...}
```svelte
<!--- copy: false --->
{#each expression as name}...{/each}
```
```svelte
<!--- copy: false --->
{#each expression as name, index}...{/each}
```
```svelte
<!--- copy: false --->
{#each expression as name (key)}...{/each}
```
```svelte
<!--- copy: false --->
{#each expression as name, index (key)}...{/each}
```
```svelte
<!--- copy: false --->
{#each expression as name}...{:else}...{/each}
```
Iterating over lists of values can be done with an each block.
```svelte
<h1>Shopping list</h1>
<ul>
{#each items as item}
<li>{item.name} x {item.qty}</li>
{/each}
</ul>
```
You can use each blocks to iterate over any array or array-like value — that is, any object with a `length` property.
An each block can also specify an _index_, equivalent to the second argument in an `array.map(...)` callback:
```svelte
{#each items as item, i}
<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}
```
If a _key_ expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change.
```svelte
{#each items as item (item.id)}
<li>{item.name} x {item.qty}</li>
{/each}
<!-- or with additional index value -->
{#each items as item, i (item.id)}
<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}
```
You can freely use destructuring and rest patterns in each blocks.
An each block can also have an `{:else}` clause, which is rendered if the list is empty.
```svelte
{#each todos as todo}
<p>{todo.text}</p>
{:else}
<p>No tasks today!</p>
{/each}
```
It is possible to iterate over iterables like `Map` or `Set`. Iterables need to be finite and static (they shouldn't change while being iterated over). Under the hood, they are transformed to an array using `Array.from` before being passed off to rendering. If you're writing performance-sensitive code, try to avoid iterables and use regular arrays as they are more performant.
## Other block types
Svelte also provides [`#snippet`](snippets), [`#key`](transitions-and-animations) and [`#await`](data-fetching) blocks. You can find out more about them in their respective sections.
Fetching data is a fundamental part of apps interacting with the outside world. Svelte is unopinionated with how you fetch your data. The simplest way would be using the built-in `fetch` method:
While this works, it makes working with promises somewhat unergonomic. Svelte alleviates this problem using the `#await` block.
## {#await ...}
## SvelteKit loaders
Fetching inside your components is great for simple use cases, but it's prone to data loading waterfalls and makes code harder to work with because of the promise handling. SvelteKit solves this problem by providing a opinionated data loading story that is coupled to its router. Learn more about it [in the docs](../kit).
- how to use, best practises (like encapsulating them) -->
Context allows components to access values owned by parent components without passing them down as props (potentially through many layers of intermediate components, known as 'prop-drilling'). The parent component sets context with `setContext(key, value)`...
Most state is component-level state that lives as long as its component lives. There's also section-wide or app-wide state however, which also needs to be handled somehow.
The easiest way to do that is to create global state and just import that.
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
```ts
/// file: state.svelte.js
export const myGlobalState = $state({
user: {
/* ... */
}
/* ... */
});
setContext('my-context', 'hello from Parent.svelte');
</script>
```
...and the child retrieves it with `getContext`:
```svelte
<!--- file: App.svelte --->
<!--- file: Child.svelte --->
<script>
import { myGlobalState } from './state.svelte.js';
// ...
import { getContext } from 'svelte';
const message = getContext('my-context');
</script>
<h1>{message}, inside Child.svelte</h1>
```
This has a few drawbacks though:
This is particularly useful when `Parent.svelte` is not directly aware of `Child.svelte`, but instead renders it as part of a `children` [snippet](snippet) ([demo](/playground/untitled#H4sIAAAAAAAAE42Q3W6DMAyFX8WyJgESK-oto6hTX2D3YxcM3IIUQpR40yqUd58CrCXsp7tL7HNsf2dAWXaEKR56yfTBGOOxFWQwfR6Qz8q1XAHjL-GjUhvzToJd7bU09FO9ctMkG0wxM5VuFeeFLLjtVK8ZnkpNkuGo-w6CTTJ9Z3PwsBAemlbUF934W8iy5DpaZtOUcU02-ZLcaS51jHEkTFm_kY1_wfOO8QnXrb8hBzDEc6pgZ4gFoyz4KgiD7nxfTe8ghqAhIfrJ46cTzVZBbkPlODVJsLCDO6V7ZcJoncyw1yRr0hd1GNn_ZbEM3I9i1bmVxOlWElUvDUNHxpQngt3C4CXzjS1rtvkw22wMrTRtTbC8Lkuabe7jvthPPe3DofYCAAA=)):
```svelte
<Parent>
<Child/>
</Parent>
```
- it only safely works when your global state is only used client-side - for example, when you're building a single page application that does not render any of your components on the server. If your state ends up being managed and updated on the server, it could end up being shared between sessions and/or users, causing bugs
- it may give the false impression that certain state is global when in reality it should only used in a certain part of your app
The key (`'my-context'`, in the example above) and the context itself can be any JavaScript value.
To solve these drawbacks, Svelte provides a few `context` primitives which alleviate these problems.
In addition to [`setContext`](svelte#setContext) and [`getContext`](svelte#getContext), Svelte exposes [`hasContext`](svelte#hasContext) and [`getAllContexts`](svelte#getAllContexts) functions.
## Setting and getting context
## Using context with state
To associate an arbitrary object with the current component, use `setContext`.
You can store reactive state in context ([demo](/playground/untitled#H4sIAAAAAAAAE41R0W6DMAz8FSuaBNUQdK8MkKZ-wh7HHihzu6hgosRMm1D-fUpSVNq12x4iEvvOx_kmQU2PIhfP3DCCJGgHYvxkkYid7NCI_GUS_KUcxhVEMjOelErNB3bsatvG4LW6n0ZsRC4K02qpuKqpZtmrQTNMYJA3QRAs7PTQQxS40eMCt3mX3duxnWb-lS5h7nTI0A4jMWoo4c44P_Hku-zrOazdy64chWo-ScfRkRgl8wgHKrLTH1OxHZkHgoHaTraHcopXUFYzPPVfuC_hwQaD1GrskdiNCdQwJljJqlvXfyqVsA5CGg0uRUQifHw56xFtciO75QrP07vo_JXf_tf8yK2ezDKY_ZWt_1y2qqYzv7bI1IW1V_sN19m-07wCAAA=))...
```svelte
<script>
import { setContext } from 'svelte';
import Child from './Child.svelte';
setContext('key', value);
let counter = $state({
count: 0
});
setContext('counter', counter);
</script>
<buttononclick={()=> counter.count += 1}>
increment
</button>
<Child/>
<Child/>
<Child/>
```
The context is then available to children of the component (including slotted content) with `getContext`.
...though note that if you _reassign_`counter` instead of updating it, you will 'break the link' — in other words instead of this...
```svelte
<script>
import { getContext } from 'svelte';
const value = getContext('key');
</script>
<buttononclick={()=> counter = { count: 0 }}>
reset
</button>
```
`setContext` and `getContext` solve the above problems:
...you must do this:
- the state is not global, it's scoped to the component. That way it's safe to render your components on the server and not leak state
- it's clear that the state is not global but rather scoped to a specific component tree and therefore can't be used in other parts of your app
```svelte
<buttononclick={()=> +++counter.count = 0+++}>
reset
</button>
```
> [!NOTE] `setContext`/`getContext` must be called during component initialisation.
Svelte will warn you if you get it wrong.
Context is not inherently reactive. If you need reactive values in context then you can pass a `$state` object into context, whose properties _will_ be reactive.
## Type-safe context
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
A useful pattern is to wrap the calls to `setContext` and `getContext` inside helper functions that let you preserve type safety:
To check whether a given `key` has been set in the context of a parent component, use `hasContext`.
## Replacing global state
```svelte
<script>
import { hasContext } from 'svelte';
When you have state shared by many different components, you might be tempted to put it in its own module and just import it wherever it's needed:
if (hasContext('key')) {
// do something
```js
/// file: state.svelte.js
export const myGlobalState = $state({
user: {
// ...
}
</script>
// ...
});
```
You can also retrieve the whole context map that belongs to the closest parent component using `getAllContexts`. This is useful, for example, if you programmatically create a component and want to pass the existing context to it.
In many cases this is perfectly fine, but there is a risk: if you mutate the state during server-side rendering (which is discouraged, but entirely possible!)...
```svelte
<!--- file: App.svelte ---->
<script>
import { getAllContexts } from 'svelte';
import { myGlobalState } from 'svelte';
const contexts = getAllContexts();
let { data } = $props();
if (data.user) {
myGlobalState.user = data.user;
}
</script>
```
## Encapsulating context interactions
The above methods are very unopinionated about how to use them. When your app grows in scale, it's worthwhile to encapsulate setting and getting the context into functions and properly type them.
```ts
// @errors: 2304
import { getContext, setContext } from 'svelte';
let userKey = Symbol('user');
export function setUserContext(user: User) {
setContext(userKey, user);
}
export function getUserContext(): User {
return getContext(userKey) as User;
}
```
...then the data may be accessible by the _next_ user. Context solves this problem because it is not shared between requests.
@ -10,13 +10,13 @@ You don't have to migrate to the new syntax right away - Svelte 5 still supports
At the heart of Svelte 5 is the new runes API. Runes are basically compiler instructions that inform Svelte about reactivity. Syntactically, runes are functions starting with a dollar-sign.
### let -> $state
### let → $state
In Svelte 4, a `let` declaration at the top level of a component was implicitly reactive. In Svelte 5, things are more explicit: a variable is reactive when created using the `$state` rune. Let's migrate the counter to runes mode by wrapping the counter in `$state`:
```svelte
<script>
let count = +++$state(+++0+++)+++;
let count = +++$state(0)+++;
</script>
```
@ -25,14 +25,14 @@ Nothing else changes. `count` is still the number itself, and you read and write
> [!DETAILS] Why we did this
> `let` being implicitly reactive at the top level worked great, but it meant that reactivity was constrained - a `let` declaration anywhere else was not reactive. This forced you to resort to using stores when refactoring code out of the top level of components for reuse. This meant you had to learn an entirely separate reactivity model, and the result often wasn't as nice to work with. Because reactivity is more explicit in Svelte 5, you can keep using the same API outside the top level of components. Head to [the tutorial](/tutorial) to learn more.
### $: -> $derived/$effect
### $: → $derived/$effect
In Svelte 4, a `$:` statement at the top level of a component could be used to declare a derivation, i.e. state that is entirely defined through a computation of other state. In Svelte 5, this is achieved using the `$derived` rune:
@ -42,7 +42,8 @@ A `$:` statement could also be used to create side effects. In Svelte 5, this is
```svelte
<script>
let count = +++$state(+++0+++)+++;
let count = $state(0);
---$:---+++$effect(() =>+++ {
if (count > 5) {
alert('Count is too high!');
@ -51,6 +52,8 @@ A `$:` statement could also be used to create side effects. In Svelte 5, this is
</script>
```
Note that [when `$effect` runs is different]($effect#Understanding-dependencies) than when `$:` runs.
> [!DETAILS] Why we did this
> `$:` was a great shorthand and easy to get started with: you could slap a `$:` in front of most code and it would somehow work. This intuitiveness was also its drawback the more complicated your code became, because it wasn't as easy to reason about. Was the intent of the code to create a derivation, or a side effect? With `$derived` and `$effect`, you have a bit more up-front decision making to do (spoiler alert: 90% of the time you want `$derived`), but future-you and other developers on your team will have an easier time.
>
@ -71,14 +74,14 @@ A `$:` statement could also be used to create side effects. In Svelte 5, this is
> - executing dependencies as needed and therefore being immune to ordering problems
> - being TypeScript-friendly
### export let -> $props
### export let → $props
In Svelte 4, properties of a component were declared using `export let`. Each property was one declaration. In Svelte 5, all properties are declared through the `$props` rune, through destructuring:
@ -190,9 +193,9 @@ This function is deprecated in Svelte 5. Instead, components should accept _call
```svelte
<!--- file: Pump.svelte --->
<script>
---import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
---
---import { createEventDispatcher } from 'svelte';---
---const dispatch = createEventDispatcher();---
+++let { inflate, deflate } = $props();+++
let power = $state(5);
</script>
@ -464,11 +467,11 @@ By now you should have a pretty good understanding of the before/after and how t
We thought the same, which is why we provide a migration script to do most of the migration automatically. You can upgrade your project by using `npx sv migrate svelte-5`. This will do the following things:
- bump core dependencies in your `package.json`
- migrate to runes (`let` ->`$state` etc)
- migrate to event attributes for DOM elements (`on:click` ->`onclick`)
- migrate slot creations to render tags (`<slot/>` ->`{@render children()}`)
- migrate slot usages to snippets (`<divslot="x">...</div>` ->`{#snippet x()}<div>...</div>{/snippet}`)
You can also migrate a single component in VS Code through the `Migrate Component to Svelte 5 Syntax` command, or in our Playground through the `Migrate` button.
@ -96,7 +96,7 @@ However, you can use any router library. A lot of people use [page.js](https://g
If you prefer a declarative HTML approach, there's the isomorphic [svelte-routing](https://github.com/EmilTholin/svelte-routing) library and a fork of it called [svelte-navigator](https://github.com/mefechoel/svelte-navigator) containing some additional functionality.
If you need hash-based routing on the client side, check out [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router) or [abstract-state-router](https://github.com/TehShrike/abstract-state-router/).
If you need hash-based routing on the client side, check out the [hash option](https://svelte.dev/docs/kit/configuration#router) in SvelteKit, [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router), or [abstract-state-router](https://github.com/TehShrike/abstract-state-router/).
[Routify](https://routify.dev) is another filesystem-based router, similar to SvelteKit's router. Version 3 supports Svelte's native SSR.
@ -21,7 +21,7 @@ A component is attempting to bind to a non-bindable property `%key%` belonging t
### component_api_changed
```
%parent% called `%method%` on an instance of %component%, which is no longer valid in Svelte 5
Calling `%method%` on a component instance (of %component%) is no longer valid in Svelte 5
```
See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more information.
@ -122,14 +122,39 @@ Property descriptors defined on `$state` objects must contain `value` and always
Cannot set prototype of `$state` object
```
### state_unsafe_local_read
### state_unsafe_mutation
```
Reading state that was created inside the same derived is forbidden. Consider using `untrack` to read locally created state
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
```
### state_unsafe_mutation
This error occurs when state is updated while evaluating a `$derived`. You might encounter it while trying to 'derive' two pieces of state in one go:
```svelte
<script>
let count = $state(0);
let even = $state(true);
let odd = $derived.by(() => {
even = count % 2 === 0;
return !even;
});
</script>
<buttononclick={()=> count++}>{count}</button>
<p>{count} is even: {even}</p>
<p>{count} is odd: {odd}</p>
```
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
This is forbidden because it introduces instability: if `<p>{count} is even: {even}</p>` is updated before `odd` is recalculated, `even` will be stale. In most cases the solution is to make everything derived:
```js
let count = 0;
// ---cut---
let even = $derived(count % 2 === 0);
let odd = $derived(!even);
```
If side-effects are unavoidable, use [`$effect`]($effect) instead.
@ -177,7 +177,7 @@ Tried to unmount a component that was not mounted
### ownership_invalid_binding
```
%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
%parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
```
Consider three components `GrandParent`, `Parent` and `Child`. If you do `<GrandParent bind:value>`, inside `GrandParent` pass on the variable via `<Parent {value} />` (note the missing `bind:`) and then do `<Child bind:value>` inside `Parent`, this warning is thrown.
@ -187,11 +187,7 @@ To fix it, `bind:` to the value instead of just passing a property (i.e. in this
### ownership_invalid_mutation
```
Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
```
```
%component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
Mutating unbound props (`%name%`, at %location%) is strongly discouraged. Consider using `bind:%prop%={...}` in %parent% (or using a callback) instead
@ -84,6 +84,12 @@ Attribute values containing `{...}` must be enclosed in quote marks, unless the
`bind:group` can only bind to an Identifier or MemberExpression
```
### bind_group_invalid_snippet_parameter
```
Cannot `bind:group` to a snippet parameter
```
### bind_invalid_expression
```
@ -229,7 +235,31 @@ A top-level `:global {...}` block can only contain rules, not declarations
### css_global_block_invalid_list
```
A `:global` selector cannot be part of a selector list with more than one item
A `:global` selector cannot be part of a selector list with entries that don't contain `:global`
```
The following CSS is invalid:
```css
:global, x {
y {
color: red;
}
}
```
This is mixing a `:global` block, which means "everything in here is unscoped", with a scoped selector (`x` in this case). As a result it's not possible to transform the inner selector (`y` in this case) into something that satisfies both requirements. You therefore have to split this up into two selectors:
```css
:global {
y {
color: red;
}
}
x y {
color: red;
}
```
### css_global_block_invalid_modifier
@ -666,6 +696,12 @@ Cannot access a computed property of a rune
@ -823,15 +823,16 @@ See [the migration guide](v5-migration-guide#Snippets-instead-of-slots) for more
### state_referenced_locally
```
State referenced in its own scope will never update. Did you mean to reference it inside a closure?
This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
```
This warning is thrown when the compiler detects the following:
- A reactive variable is declared
- the variable is reassigned
- the variable is referenced inside the same scope it is declared and it is a non-reactive context
- ...and later reassigned...
- ...and referenced in the same scope
In this case, the state reassignment will not be noticed by whatever you passed it to. For example, if you pass the state to a function, that function will not notice the updates:
This 'breaks the link' to the original state declaration. For example, if you pass the state to a function, the function loses access to the state once it is reassigned:
@ -38,6 +38,12 @@ This error would be thrown in a setup like this:
Here, `List.svelte` is using `{@render children(item)` which means it expects `Parent.svelte` to use snippets. Instead, `Parent.svelte` uses the deprecated `let:` directive. This combination of APIs is incompatible, hence the error.
### invalid_snippet_arguments
```
A snippet function was passed invalid arguments. Snippets should only be instantiated via `{@render ...}`
```
### lifecycle_outside_component
```
@ -62,6 +68,43 @@ Certain lifecycle methods can only be used during component initialisation. To f
<buttononclick={handleClick}>click me</button>
```
### snippet_without_render_tag
```
Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
```
A component throwing this error will look something like this (`children` is not being rendered):
```svelte
<script>
let { children } = $props();
</script>
{children}
```
...or like this (a parent component is passing a snippet where a non-snippet value is expected):
```svelte
<!--- file: Parent.svelte --->
<ChildComponent>
{#snippet label()}
<span>Hi!</span>
{/snippet}
</ChildComponent>
```
```svelte
<!--- file: Child.svelte --->
<script>
let { label } = $props();
</script>
<!-- This component doesn't expect a snippet, but the parent provided one -->
- fix: ensure clearing of old values happens independent of root flushes ([#15664](https://github.com/sveltejs/svelte/pull/15664))
## 5.25.6
### Patch Changes
- fix: ignore generic type arguments while creating AST ([#15659](https://github.com/sveltejs/svelte/pull/15659))
- fix: better consider component and its snippets during css pruning ([#15630](https://github.com/sveltejs/svelte/pull/15630))
## 5.25.5
### Patch Changes
- fix: add setters to `$derived` class properties ([#15628](https://github.com/sveltejs/svelte/pull/15628))
- fix: silence assignment warning on more function bindings ([#15644](https://github.com/sveltejs/svelte/pull/15644))
- fix: make sure CSS is preserved during SSR with bindings ([#15645](https://github.com/sveltejs/svelte/pull/15645))
## 5.25.4
### Patch Changes
- fix: support TS type assertions ([#15642](https://github.com/sveltejs/svelte/pull/15642))
- fix: ensure `undefined` class still applies scoping class, if necessary ([#15643](https://github.com/sveltejs/svelte/pull/15643))
## 5.25.3
### Patch Changes
- fix: prevent state runes from being called with spread ([#15585](https://github.com/sveltejs/svelte/pull/15585))
## 5.25.2
### Patch Changes
- feat: migrate reassigned deriveds to `$derived` ([#15581](https://github.com/sveltejs/svelte/pull/15581))
## 5.25.1
### Patch Changes
- fix: prevent dev server from throwing errors when attempting to retrieve the proxied value of an iframe's contentWindow ([#15577](https://github.com/sveltejs/svelte/pull/15577))
## 5.25.0
### Minor Changes
- feat: make deriveds writable ([#15570](https://github.com/sveltejs/svelte/pull/15570))
## 5.24.1
### Patch Changes
- fix: use `get` in constructor for deriveds ([#15300](https://github.com/sveltejs/svelte/pull/15300))
- fix: ensure toStore root effect is connected to correct parent effect ([#15574](https://github.com/sveltejs/svelte/pull/15574))
## 5.24.0
### Minor Changes
- feat: allow state created in deriveds/effects to be written/read locally without self-invalidation ([#15553](https://github.com/sveltejs/svelte/pull/15553))
### Patch Changes
- fix: check if DOM prototypes are extensible ([#15569](https://github.com/sveltejs/svelte/pull/15569))
- Keep inlined trailing JSDoc comments of properties when running svelte-migrate ([#15567](https://github.com/sveltejs/svelte/pull/15567))
- fix: simplify set calls for proxyable values ([#15548](https://github.com/sveltejs/svelte/pull/15548))
- fix: don't depend on deriveds created inside the current reaction ([#15564](https://github.com/sveltejs/svelte/pull/15564))
## 5.23.2
### Patch Changes
- fix: don't hoist listeners that access non hoistable snippets ([#15534](https://github.com/sveltejs/svelte/pull/15534))
- fix: respect `svelte-ignore hydration_attribute_changed` on elements with spread attributes ([#15443](https://github.com/sveltejs/svelte/pull/15443))
- fix: always use `setAttribute` when setting `style` ([#15323](https://github.com/sveltejs/svelte/pull/15323))
- fix: make `style:` directive and CSS handling more robust ([#15418](https://github.com/sveltejs/svelte/pull/15418))
## 5.22.4
### Patch Changes
- fix: never deduplicate expressions in templates ([#15451](https://github.com/sveltejs/svelte/pull/15451))
## 5.22.3
### Patch Changes
- fix: run effect roots in tree order ([#15446](https://github.com/sveltejs/svelte/pull/15446))
## 5.22.2
### Patch Changes
- fix: correctly set `is_updating` before flushing root effects ([#15442](https://github.com/sveltejs/svelte/pull/15442))
> %parent% called `%method%` on an instance of %component%, which is no longer valid in Svelte 5
> Calling `%method%` on a component instance (of %component%) is no longer valid in Svelte 5
See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more information.
@ -80,10 +80,37 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long
> Cannot set prototype of `$state` object
## state_unsafe_local_read
> Reading state that was created inside the same derived is forbidden. Consider using `untrack` to read locally created state
## state_unsafe_mutation
> Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
This error occurs when state is updated while evaluating a `$derived`. You might encounter it while trying to 'derive' two pieces of state in one go:
```svelte
<script>
let count = $state(0);
let even = $state(true);
let odd = $derived.by(() => {
even = count % 2 === 0;
return !even;
});
</script>
<buttononclick={()=> count++}>{count}</button>
<p>{count} is even: {even}</p>
<p>{count} is odd: {odd}</p>
```
This is forbidden because it introduces instability: if `<p>{count} is even: {even}</p>` is updated before `odd` is recalculated, `even` will be stale. In most cases the solution is to make everything derived:
```js
let count = 0;
// ---cut---
let even = $derived(count % 2 === 0);
let odd = $derived(!even);
```
If side-effects are unavoidable, use [`$effect`]($effect) instead.
@ -144,7 +144,7 @@ During development, this error is often preceeded by a `console.error` detailing
## ownership_invalid_binding
> %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
> %parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
Consider three components `GrandParent`, `Parent` and `Child`. If you do `<GrandParent bind:value>`, inside `GrandParent` pass on the variable via `<Parent {value} />` (note the missing `bind:`) and then do `<Child bind:value>` inside `Parent`, this warning is thrown.
@ -152,9 +152,7 @@ To fix it, `bind:` to the value instead of just passing a property (i.e. in this
## ownership_invalid_mutation
> Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
> %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
> Mutating unbound props (`%name%`, at %location%) is strongly discouraged. Consider using `bind:%prop%={...}` in %parent% (or using a callback) instead
> A `:global` selector cannot be part of a selector list with more than one item
> A `:global` selector cannot be part of a selector list with entries that don't contain `:global`
The following CSS is invalid:
```css
:global, x {
y {
color: red;
}
}
```
This is mixing a `:global` block, which means "everything in here is unscoped", with a scoped selector (`x` in this case). As a result it's not possible to transform the inner selector (`y` in this case) into something that satisfies both requirements. You therefore have to split this up into two selectors:
@ -54,14 +54,15 @@ To fix this, wrap your variable declaration with `$state`.
## state_referenced_locally
> State referenced in its own scope will never update. Did you mean to reference it inside a closure?
> This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
This warning is thrown when the compiler detects the following:
- A reactive variable is declared
- the variable is reassigned
- the variable is referenced inside the same scope it is declared and it is a non-reactive context
- ...and later reassigned...
- ...and referenced in the same scope
In this case, the state reassignment will not be noticed by whatever you passed it to. For example, if you pass the state to a function, that function will not notice the updates:
This 'breaks the link' to the original state declaration. For example, if you pass the state to a function, the function loses access to the state once it is reassigned:
@ -32,6 +32,10 @@ This error would be thrown in a setup like this:
Here, `List.svelte` is using `{@render children(item)` which means it expects `Parent.svelte` to use snippets. Instead, `Parent.svelte` uses the deprecated `let:` directive. This combination of APIs is incompatible, hence the error.
## invalid_snippet_arguments
> A snippet function was passed invalid arguments. Snippets should only be instantiated via `{@render ...}`
## lifecycle_outside_component
> `%name%(...)` can only be used during component initialisation
@ -54,6 +58,41 @@ Certain lifecycle methods can only be used during component initialisation. To f
<buttononclick={handleClick}>click me</button>
```
## snippet_without_render_tag
> Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
A component throwing this error will look something like this (`children` is not being rendered):
```svelte
<script>
let { children } = $props();
</script>
{children}
```
...or like this (a parent component is passing a snippet where a non-snippet value is expected):
```svelte
<!--- file: Parent.svelte --->
<ChildComponent>
{#snippet label()}
<span>Hi!</span>
{/snippet}
</ChildComponent>
```
```svelte
<!--- file: Child.svelte --->
<script>
let { label } = $props();
</script>
<!-- This component doesn't expect a snippet, but the parent provided one -->
<p>{label}</p>
```
## store_invalid_shape
> `%name%` is not a store with a `subscribe` method
e(node,'css_global_block_invalid_list',`A \`:global\` selector cannot be part of a selector list with more than one item\nhttps://svelte.dev/e/css_global_block_invalid_list`);
e(node,'css_global_block_invalid_list',`A \`:global\` selector cannot be part of a selector list with entries that don't contain \`:global\`\nhttps://svelte.dev/e/css_global_block_invalid_list`);
}
/**
@ -770,6 +780,15 @@ export function bind_group_invalid_expression(node) {
e(node,'bind_group_invalid_expression',`\`bind:group\` can only bind to an Identifier or MemberExpression\nhttps://svelte.dev/e/bind_group_invalid_expression`);
e(node,'bind_group_invalid_snippet_parameter',`Cannot \`bind:group\` to a snippet parameter\nhttps://svelte.dev/e/bind_group_invalid_snippet_parameter`);