You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: apps/svelte.dev/content/docs/svelte/01-introduction/03-reactivity-fundamentals.md
-22Lines changed: 0 additions & 22 deletions
Original file line number
Diff line number
Diff line change
@@ -40,28 +40,6 @@ class Todo {
40
40
}
41
41
```
42
42
43
-
> In this example, the compiler transforms `done` and `text` into `get`/`set` methods on the class prototype referencing private fields
44
-
45
-
Objects and arrays [are made deeply reactive](/#H4sIAAAAAAAAE42QwWrDMBBEf2URhUhUNEl7c21DviPOwZY3jVpZEtIqUBz9e-UUt9BTj7M784bdmZ21wciq48xsPyGr2MF7Jhl9-kXEKxrCoqNLQS2TOqqgPbWd7cgggU3TgCFCAw-RekJ-3Et4lvByEq-drbe_dlsPichZcFYZrT6amQto2pXw5FO88FUYtG90gUfYi3zvWrYL75vxL57zfA07_zfr23k1vjtt-aZ0bQTcbrDL5ZifZcAxKeS8lzDc8X0xDhJ2ItdbX1jlOZMb9VnjyCoKCfMpfwG975NFVwEAAA==) by wrapping them with [`Proxies`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy):
Copy file name to clipboardExpand all lines: apps/svelte.dev/content/docs/svelte/03-runes/01-state.md
+211Lines changed: 211 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -7,3 +7,214 @@ title: State
7
7
- using classes
8
8
- getters/setters (what to do to keep reactivity "alive")
9
9
- universal reactivity
10
+
11
+
Svelte 5 uses _runes_, a powerful set of primitives for controlling reactivity inside your Svelte components and inside `.svelte.js` and `.svelte.ts` modules.
12
+
13
+
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. This page describes the runes that are concerned with managing state in your application.
14
+
15
+
## `$state`
16
+
17
+
The `$state` rune is the at the heart of the runes API. It is used to declare reactive state:
18
+
19
+
```svelte
20
+
<script>
21
+
let count = $state(0);
22
+
</script>
23
+
24
+
<button onclick={() => count++}>
25
+
clicks: {count}
26
+
</button>
27
+
```
28
+
29
+
Variables declared with `$state` are the variable _itself_, in other words there's no wrapper around the value that it contains. This is possible thanks to the compiler-nature of Svelte. As such, updating state is done through simple reassignment.
30
+
31
+
You can also use `$state` in class fields (whether public or private):
32
+
33
+
```js
34
+
// @errors: 7006 2554
35
+
classTodo {
36
+
done =$state(false);
37
+
text =$state();
38
+
39
+
constructor(text) {
40
+
this.text= text;
41
+
}
42
+
43
+
reset() {
44
+
this.text='';
45
+
this.done=false;
46
+
}
47
+
}
48
+
```
49
+
50
+
> In this example, the compiler transforms `done` and `text` into `get`/`set` methods on the class prototype referencing private fields
51
+
52
+
Objects and arrays are made deeply reactive by wrapping them with [`Proxies`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). What that means is that in the following example, we can mutate the `entries` object and the UI will still update - but only the list item that is actually changed will rerender:
<button onclick={() => entries[1].text = 'baz'}>change second entry text</button>
64
+
```
65
+
66
+
## `$state.frozen`
67
+
68
+
State declared with `$state.frozen` cannot be mutated; it can only be _reassigned_. In other words, rather than assigning to a property of an object, or using an array method like `push`, replace the object or array altogether if you'd like to update it:
This can improve performance with large arrays and objects that you weren't planning to mutate anyway, since it avoids the cost of making them reactive. Note that frozen state can _contain_ reactive state (for example, a frozen array of reactive objects).
83
+
84
+
> Objects and arrays passed to `$state.frozen` will be shallowly frozen using `Object.freeze()`. If you don't want this, pass in a clone of the object or array instead.
85
+
86
+
## `$state.snapshot`
87
+
88
+
To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`:
89
+
90
+
```svelte
91
+
<script>
92
+
let counter = $state({ count: 0 });
93
+
94
+
function onclick() {
95
+
// Will log `{ count: ... }` rather than `Proxy { ... }`
96
+
console.log($state.snapshot(counter));
97
+
}
98
+
</script>
99
+
```
100
+
101
+
This is handy when you want to pass some state to an external library or API that doesn't expect a proxy, such as `structuredClone`.
102
+
103
+
> Note that `$state.snapshot` will clone the data when removing reactivity. If the value passed isn't a `$state` proxy, it will be returned as-is.
104
+
105
+
## `$state.is`
106
+
107
+
Sometimes you might need to compare two values, one of which is a reactive `$state(...)` proxy but the other is not. For this you can use `$state.is(a, b)`:
108
+
109
+
```svelte
110
+
<script>
111
+
let foo = $state({});
112
+
let bar = {};
113
+
114
+
foo.bar = bar;
115
+
116
+
console.log(foo.bar === bar); // false — `foo.bar` is a reactive proxy
117
+
console.log($state.is(foo.bar, bar)); // true
118
+
</script>
119
+
```
120
+
121
+
This is handy when you might want to check if the object exists within a deeply reactive object/array.
122
+
123
+
## `$derived`
124
+
125
+
Derived state is declared with the `$derived` rune:
126
+
127
+
```svelte
128
+
<script>
129
+
let count = $state(0);
130
+
let doubled = $derived(count * 2);
131
+
</script>
132
+
133
+
<button onclick={() => count++}>
134
+
{doubled}
135
+
</button>
136
+
137
+
<p>{count} doubled is {doubled}</p>
138
+
```
139
+
140
+
The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions.
141
+
142
+
As with `$state`, you can mark class fields as `$derived`.
143
+
144
+
## `$derived.by`
145
+
146
+
Sometimes you need to create complex derivations that don't fit inside a short expression. In these cases, you can use `$derived.by` which accepts a function as its argument.
In essence, `$derived(expression)` is equivalent to `$derived.by(() => expression)`.
166
+
167
+
## Universal reactivity
168
+
169
+
In the examples above, `$state` and `$derived` only appear at the top level of components. You can also use them within functions or even outside Svelte components inside `.svelte.js` or `.svelte.ts` modules.
There are a few things to note in the above example:
200
+
201
+
- We're using getters to transport reactivity across the function boundary. This way we keep reactivity "alive". If we were to return the value itself, it would be fixed to the value at that point in time. This is no different to how regular JavaScript variables behave.
202
+
- We're not destructuring the counter at the usage site. Because we're using getters, destructuring would fix `count` and `double` to the value at that point in time. To keep the getters "alive", we're not using destructuring. Again, this is how regular JavaScript works.
203
+
204
+
If you have shared state you want to manipulate from various places, you don't need to resort to getters. Instead, you can take advantage of `$state` being deeply reactive and only update its properties, not the value itself:
0 commit comments