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/02-runes/02-$state.md
+135-7Lines changed: 135 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -36,12 +36,7 @@ let todos = $state([
36
36
...modifying an individual todo's property will trigger updates to anything in your UI that depends on that specific property:
37
37
38
38
```js
39
-
// @filename: ambient.d.ts
40
-
declare global {
41
-
const todos:Array<{ done:boolean, text:string }>
42
-
}
43
-
44
-
// @filename: index.js
39
+
let todos = [{ done:false, text:'add more todos' }];
45
40
// ---cut---
46
41
todos[0].done=!todos[0].done;
47
42
```
@@ -64,6 +59,17 @@ todos.push({
64
59
65
60
> [!NOTE] When you update properties of proxies, the original object is _not_ mutated.
66
61
62
+
Note that if you destructure a reactive value, the references are not reactive — as in normal JavaScript, they are evaluated at the point of destructuring:
63
+
64
+
```js
65
+
let todos = [{ done:false, text:'add more todos' }];
66
+
// ---cut---
67
+
let { done, text } = todos[0];
68
+
69
+
// this will not affect the value of `done`
70
+
todos[0].done=!todos[0].done;
71
+
```
72
+
67
73
### Classes
68
74
69
75
You can also use `$state` in class fields (whether public or private):
@@ -85,7 +91,42 @@ class Todo {
85
91
}
86
92
```
87
93
88
-
> [!NOTE] The compiler transforms `done` and `text` into `get`/`set` methods on the class prototype referencing private fields.
94
+
> [!NOTE] The compiler transforms `done` and `text` into `get`/`set` methods on the class prototype referencing private fields. This means the properties are not enumerable.
95
+
96
+
When calling methods in JavaScript, the value of [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) matters. This won't work, because `this` inside the `reset` method will be the `<button>` rather than the `Todo`:
97
+
98
+
```svelte
99
+
<button onclick={todo.reset}>
100
+
reset
101
+
</button>
102
+
```
103
+
104
+
You can either use an inline function...
105
+
106
+
```svelte
107
+
<button onclick=+++{() => todo.reset()}>+++
108
+
reset
109
+
</button>
110
+
```
111
+
112
+
...or use an arrow function in the class definition:
113
+
114
+
```js
115
+
// @errors: 7006 2554
116
+
classTodo {
117
+
done =$state(false);
118
+
text =$state();
119
+
120
+
constructor(text) {
121
+
this.text= text;
122
+
}
123
+
124
+
+++reset= () => {+++
125
+
this.text='';
126
+
this.done=false;
127
+
}
128
+
}
129
+
```
89
130
90
131
## `$state.raw`
91
132
@@ -127,3 +168,90 @@ To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snaps
127
168
```
128
169
129
170
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`.
171
+
172
+
## Passing state into functions
173
+
174
+
JavaScript is a _pass-by-value_ language — when you call a function, the arguments are the _values_ rather than the _variables_. In other words:
175
+
176
+
```js
177
+
/// file: index.js
178
+
// @filename: index.js
179
+
// ---cut---
180
+
/**
181
+
* @param{number}a
182
+
* @param{number}b
183
+
*/
184
+
functionadd(a, b) {
185
+
return a + b;
186
+
}
187
+
188
+
let a =1;
189
+
let b =2;
190
+
let total =add(a, b);
191
+
console.log(total); // 3
192
+
193
+
a =3;
194
+
b =4;
195
+
console.log(total); // still 3!
196
+
```
197
+
198
+
If `add` wanted to have access to the _current_ values of `a` and `b`, and to return the current `total` value, you would need to use functions instead:
199
+
200
+
```js
201
+
/// file: index.js
202
+
// @filename: index.js
203
+
// ---cut---
204
+
/**
205
+
* @param{() => number}getA
206
+
* @param{() => number}getB
207
+
*/
208
+
functionadd(+++getA, getB+++) {
209
+
return+++() =>getA() +getB()+++;
210
+
}
211
+
212
+
let a =1;
213
+
let b =2;
214
+
let total = add+++(() => a, () => b)+++;
215
+
console.log(+++total()+++); // 3
216
+
217
+
a =3;
218
+
a =4;
219
+
console.log(+++total()+++); // 7
220
+
```
221
+
222
+
State in Svelte is no different — when you reference something declared with the `$state` rune...
223
+
224
+
```js
225
+
let a =+++$state(1)+++;
226
+
let b =+++$state(2)+++;
227
+
```
228
+
229
+
...you're accessing its _current value_.
230
+
231
+
Note that 'functions' is broad — it encompasses properties of proxies and [`get`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)/[`set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) properties...
232
+
233
+
```js
234
+
/// file: index.js
235
+
// @filename: index.js
236
+
// ---cut---
237
+
/**
238
+
* @param{{ a: number, b: number }}input
239
+
*/
240
+
functionadd(input) {
241
+
return {
242
+
getvalue() {
243
+
returninput.a+input.b;
244
+
}
245
+
};
246
+
}
247
+
248
+
let input =$state({ a:1, b:2 });
249
+
let total =add(input);
250
+
console.log(total.value); // 3
251
+
252
+
input.a=3;
253
+
input.b=4;
254
+
console.log(total.value); // 7
255
+
```
256
+
257
+
...though if you find yourself writing code like that, consider using [classes](#Classes) instead.
0 commit comments