Spec RegistrySpec Registry

Help your agents use open-source better. Learn more.

Find usage specs for your project’s dependencies

>

npm-svelte

Describes: npmnpm/svelte

Description
A cybernetically enhanced web application framework that compiles to highly optimized JavaScript with reactive state management and component-based architecture.
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-svelte@5.38.0

reactivity.md docs/

1
# Reactivity Control
2
3
Svelte provides functions for controlling reactive updates, managing execution timing, handling asynchronous operations, and reactive versions of built-in JavaScript objects for comprehensive reactivity.
4
5
## Capabilities
6
7
### tick
8
9
Returns a Promise that resolves after any pending state changes have been applied to the DOM.
10
11
```typescript { .api }
12
/**
13
* Returns a promise that resolves once any pending state changes have been applied
14
* @returns Promise that resolves after DOM updates
15
*/
16
function tick(): Promise<void>;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import { tick } from "svelte";
23
24
let count = $state(0);
25
let element;
26
27
async function updateAndRead() {
28
count += 1;
29
30
// Wait for DOM to update
31
await tick();
32
33
// Now we can safely read the updated DOM
34
console.log("Updated element text:", element.textContent);
35
}
36
37
// Measuring DOM changes
38
async function measureHeight(newContent) {
39
const oldHeight = element.offsetHeight;
40
41
// Update content
42
content = newContent;
43
44
// Wait for DOM update
45
await tick();
46
47
const newHeight = element.offsetHeight;
48
console.log(`Height changed from ${oldHeight} to ${newHeight}`);
49
}
50
51
// Focusing elements after conditional rendering
52
let showInput = $state(false);
53
let inputElement;
54
55
async function showAndFocus() {
56
showInput = true;
57
58
// Wait for input to be rendered
59
await tick();
60
61
// Now we can focus it
62
inputElement?.focus();
63
}
64
```
65
66
### settled
67
68
Returns a Promise that resolves when all async state updates have completed. More comprehensive than `tick()` for complex reactive chains.
69
70
```typescript { .api }
71
/**
72
* Returns a promise that resolves when all reactive updates have settled
73
* @returns Promise that resolves after all async updates
74
*/
75
function settled(): Promise<void>;
76
```
77
78
**Usage Examples:**
79
80
```typescript
81
import { settled } from "svelte";
82
83
let loading = $state(false);
84
let data = $state([]);
85
let processedData = $state([]);
86
87
// Derived values that might trigger additional updates
88
let filteredData = $derived(data.filter(item => item.active));
89
let sortedData = $derived(filteredData.sort((a, b) => a.name.localeCompare(b.name)));
90
91
async function loadAndProcess() {
92
loading = true;
93
94
// Fetch data
95
const response = await fetch("/api/data");
96
data = await response.json();
97
98
// Wait for all reactive updates to settle
99
await settled();
100
101
// Now all derived values are up to date
102
console.log("Final processed data:", sortedData);
103
loading = false;
104
}
105
106
// Complex reactive chains
107
let userInput = $state("");
108
let searchResults = $state([]);
109
let selectedItems = $state([]);
110
111
$effect(async () => {
112
if (userInput.length > 2) {
113
searchResults = await searchAPI(userInput);
114
}
115
});
116
117
async function processSelection() {
118
// Update multiple reactive values
119
selectedItems = [...selectedItems, ...searchResults.slice(0, 3)];
120
userInput = "";
121
122
// Wait for all reactive updates to complete
123
await settled();
124
125
// Safe to perform operations that depend on final state
126
saveSelections(selectedItems);
127
}
128
```
129
130
### untrack
131
132
Executes a function without creating reactive dependencies or triggering reactive updates.
133
134
```typescript { .api }
135
/**
136
* Run a function without creating dependencies on reactive state
137
* @param fn - Function to run without tracking
138
* @returns Return value of the function
139
*/
140
function untrack<T>(fn: () => T): T;
141
```
142
143
**Usage Examples:**
144
145
```typescript
146
import { untrack } from "svelte";
147
148
let count = $state(0);
149
let lastUpdate = $state(Date.now());
150
151
// Effect that doesn't depend on lastUpdate changes
152
$effect(() => {
153
console.log(`Count is ${count}`);
154
155
// Update timestamp without creating dependency
156
untrack(() => {
157
lastUpdate = Date.now();
158
});
159
});
160
161
// Conditional logging without dependency
162
let debugMode = $state(false);
163
let data = $state({ items: [] });
164
165
$effect(() => {
166
// React to data changes
167
processData(data);
168
169
// Log only if debug mode, but don't react to debugMode changes
170
untrack(() => {
171
if (debugMode) {
172
console.log("Data processed:", data);
173
}
174
});
175
});
176
177
// One-time initialization
178
let config = $state(null);
179
let initialLoad = $state(false);
180
181
$effect(() => {
182
if (config && !initialLoad) {
183
// Load data based on config
184
loadInitialData(config);
185
186
// Set flag without creating new reactive dependency
187
untrack(() => {
188
initialLoad = true;
189
});
190
}
191
});
192
```
193
194
### flushSync
195
196
Synchronously flushes any pending reactive updates. Forces immediate DOM updates.
197
198
```typescript { .api }
199
/**
200
* Synchronously flush any pending state changes and update the DOM
201
* @param fn - Optional function to run before flushing
202
* @returns Return value of fn, or void if no fn provided
203
*/
204
function flushSync<T = void>(fn?: (() => T) | undefined): T;
205
```
206
207
**Usage Examples:**
208
209
```typescript
210
import { flushSync } from "svelte";
211
212
let items = $state([]);
213
let container;
214
215
function addItemAndScroll(newItem) {
216
// Add item
217
items = [...items, newItem];
218
219
// Force immediate DOM update
220
flushSync();
221
222
// Scroll to new item (DOM is already updated)
223
const newElement = container.lastElementChild;
224
newElement.scrollIntoView();
225
}
226
227
// Batch updates with immediate flush
228
function batchUpdateWithFlush() {
229
flushSync(() => {
230
// Multiple state updates
231
count = 10;
232
name = "Updated";
233
active = true;
234
});
235
236
// DOM is immediately updated here
237
measureAndAdjust();
238
}
239
240
// Animation timing
241
let animationTarget = $state(0);
242
let element;
243
244
function animateWithPreciseTiming() {
245
animationTarget = 100;
246
247
// Ensure DOM updates immediately
248
flushSync();
249
250
// Start animation with current DOM state
251
element.animate([
252
{ transform: "translateX(0px)" },
253
{ transform: `translateX(${animationTarget}px)` }
254
], { duration: 300 });
255
}
256
```
257
258
### getAbortSignal
259
260
Returns an AbortSignal that is aborted when the current effect or derived is re-run or destroyed.
261
262
```typescript { .api }
263
/**
264
* Get an AbortSignal for the current effect or derived computation
265
* @returns AbortSignal that aborts when effect re-runs or is destroyed
266
*/
267
function getAbortSignal(): AbortSignal;
268
```
269
270
**Usage Examples:**
271
272
```typescript
273
import { getAbortSignal } from "svelte";
274
275
let userId = $state(null);
276
let userProfile = $state(null);
277
278
// Effect with automatic cancellation
279
$effect(() => {
280
if (!userId) return;
281
282
const signal = getAbortSignal();
283
284
// Fetch with automatic cancellation
285
fetch(`/api/users/${userId}`, { signal })
286
.then(r => r.json())
287
.then(profile => {
288
if (!signal.aborted) {
289
userProfile = profile;
290
}
291
})
292
.catch(err => {
293
if (!signal.aborted) {
294
console.error("Failed to fetch user:", err);
295
}
296
});
297
});
298
299
// Derived value with async computation
300
let searchQuery = $state("");
301
let searchResults = $derived.by(() => {
302
if (!searchQuery) return [];
303
304
const signal = getAbortSignal();
305
let results = [];
306
307
// Async search with cancellation
308
searchAPI(searchQuery, { signal })
309
.then(data => {
310
if (!signal.aborted) {
311
results = data;
312
}
313
});
314
315
return results;
316
});
317
318
// WebSocket connection management
319
let connected = $state(false);
320
let websocket = $state(null);
321
322
$effect(() => {
323
const signal = getAbortSignal();
324
325
const ws = new WebSocket("ws://localhost:8080");
326
websocket = ws;
327
328
ws.onopen = () => {
329
if (!signal.aborted) {
330
connected = true;
331
}
332
};
333
334
ws.onclose = () => {
335
if (!signal.aborted) {
336
connected = false;
337
}
338
};
339
340
// Cleanup when aborted
341
signal.addEventListener("abort", () => {
342
ws.close();
343
websocket = null;
344
connected = false;
345
});
346
});
347
```
348
349
### Reactive Built-in Objects
350
351
Svelte provides reactive versions of built-in JavaScript objects that automatically trigger updates when their contents change.
352
353
#### SvelteDate
354
355
A reactive version of the built-in Date object.
356
357
```typescript { .api }
358
/**
359
* Reactive Date object that triggers updates when date value changes
360
*/
361
class SvelteDate extends Date {
362
constructor(...params: any[]);
363
}
364
```
365
366
**Usage Examples:**
367
368
```typescript
369
import { SvelteDate } from "svelte/reactivity";
370
371
const date = new SvelteDate();
372
373
// Reactive clock
374
$effect(() => {
375
const interval = setInterval(() => {
376
date.setTime(Date.now());
377
}, 1000);
378
379
return () => clearInterval(interval);
380
});
381
382
// Use in template - updates automatically
383
// <p>Current time: {date.toLocaleTimeString()}</p>
384
```
385
386
#### SvelteSet
387
388
A reactive version of the built-in Set object.
389
390
```typescript { .api }
391
/**
392
* Reactive Set that triggers updates when contents change
393
*/
394
class SvelteSet<T> extends Set<T> {
395
constructor(value?: Iterable<T> | null | undefined);
396
add(value: T): this;
397
}
398
```
399
400
**Usage Examples:**
401
402
```typescript
403
import { SvelteSet } from "svelte/reactivity";
404
405
const tags = new SvelteSet(["svelte", "reactive"]);
406
407
// Reactive size
408
const tagCount = $derived(tags.size);
409
410
// Reactive membership check
411
const hasUrgent = $derived(tags.has("urgent"));
412
413
function toggleTag(tag) {
414
if (tags.has(tag)) {
415
tags.delete(tag);
416
} else {
417
tags.add(tag);
418
}
419
}
420
```
421
422
#### SvelteMap
423
424
A reactive version of the built-in Map object.
425
426
```typescript { .api }
427
/**
428
* Reactive Map that triggers updates when contents change
429
*/
430
class SvelteMap<K, V> extends Map<K, V> {
431
constructor(value?: Iterable<readonly [K, V]> | null | undefined);
432
set(key: K, value: V): this;
433
}
434
```
435
436
**Usage Examples:**
437
438
```typescript
439
import { SvelteMap } from "svelte/reactivity";
440
441
const gameBoard = new SvelteMap();
442
let currentPlayer = $state("X");
443
444
// Reactive game state
445
const winner = $derived(checkWinner(gameBoard));
446
const isFull = $derived(gameBoard.size === 9);
447
448
function makeMove(position) {
449
if (!gameBoard.has(position) && !winner) {
450
gameBoard.set(position, currentPlayer);
451
currentPlayer = currentPlayer === "X" ? "O" : "X";
452
}
453
}
454
```
455
456
#### SvelteURL
457
458
A reactive version of the built-in URL object.
459
460
```typescript { .api }
461
/**
462
* Reactive URL that triggers updates when URL properties change
463
*/
464
class SvelteURL extends URL {
465
get searchParams(): SvelteURLSearchParams;
466
}
467
```
468
469
**Usage Examples:**
470
471
```typescript
472
import { SvelteURL } from "svelte/reactivity";
473
474
const url = new SvelteURL("https://example.com/path");
475
476
// Reactive URL properties
477
const fullUrl = $derived(url.href);
478
const currentPath = $derived(url.pathname);
479
480
// Update URL reactively
481
function updatePath(newPath) {
482
url.pathname = newPath;
483
}
484
485
function updateQuery(key, value) {
486
url.searchParams.set(key, value);
487
}
488
```
489
490
#### SvelteURLSearchParams
491
492
A reactive version of URLSearchParams.
493
494
```typescript { .api }
495
/**
496
* Reactive URLSearchParams that triggers updates when parameters change
497
*/
498
class SvelteURLSearchParams extends URLSearchParams {
499
constructor(init?: string | URLSearchParams | Record<string, string>);
500
}
501
```
502
503
**Usage Examples:**
504
505
```typescript
506
import { SvelteURLSearchParams } from "svelte/reactivity";
507
508
const params = new SvelteURLSearchParams("?page=1&sort=name");
509
510
// Reactive parameter access
511
const currentPage = $derived(params.get("page") || "1");
512
const sortField = $derived(params.get("sort") || "id");
513
514
// Reactive parameter iteration
515
const allParams = $derived(Array.from(params.entries()));
516
517
function updateSort(field) {
518
params.set("sort", field);
519
}
520
```
521
522
#### MediaQuery
523
524
Creates a reactive media query that updates based on viewport changes.
525
526
```typescript { .api }
527
/**
528
* Reactive media query that updates when conditions change
529
*/
530
class MediaQuery {
531
constructor(query: string, fallback?: boolean);
532
get current(): boolean;
533
}
534
```
535
536
**Usage Examples:**
537
538
```typescript
539
import { MediaQuery } from "svelte/reactivity";
540
541
const isLargeScreen = new MediaQuery("(min-width: 1024px)");
542
const prefersReducedMotion = new MediaQuery("(prefers-reduced-motion: reduce)");
543
const isDarkMode = new MediaQuery("(prefers-color-scheme: dark)");
544
545
// Use in reactive context
546
const layoutClass = $derived(
547
isLargeScreen.current ? "desktop-layout" : "mobile-layout"
548
);
549
550
const animationDuration = $derived(
551
prefersReducedMotion.current ? 0 : 300
552
);
553
```
554
555
#### createSubscriber
556
557
Creates a subscribe function for integrating external event-based systems.
558
559
```typescript { .api }
560
/**
561
* Create a subscriber for external event-based systems
562
* @param start - Function called when first subscription occurs
563
* @returns Subscribe function
564
*/
565
function createSubscriber(
566
start: (update: () => void) => (() => void) | void
567
): () => void;
568
```
569
570
**Usage Examples:**
571
572
```typescript
573
import { createSubscriber } from "svelte/reactivity";
574
575
// Custom reactive WebSocket
576
class ReactiveWebSocket {
577
#ws;
578
#subscribe;
579
#data = null;
580
581
constructor(url) {
582
this.#subscribe = createSubscriber((update) => {
583
this.#ws = new WebSocket(url);
584
585
this.#ws.onmessage = (event) => {
586
this.#data = JSON.parse(event.data);
587
update(); // Trigger reactive updates
588
};
589
590
return () => {
591
this.#ws.close();
592
};
593
});
594
}
595
596
get data() {
597
this.#subscribe(); // Make this getter reactive
598
return this.#data;
599
}
600
}
601
602
// Usage
603
const ws = new ReactiveWebSocket("ws://localhost:8080");
604
605
$effect(() => {
606
console.log("WebSocket data:", ws.data);
607
});
608
```
609
610
## Advanced Patterns
611
612
### Debounced Effects
613
614
```typescript
615
let searchTerm = $state("");
616
let debouncedSearch = $state("");
617
618
$effect(() => {
619
const signal = getAbortSignal();
620
const timeout = setTimeout(() => {
621
if (!signal.aborted) {
622
debouncedSearch = searchTerm;
623
}
624
}, 300);
625
626
signal.addEventListener("abort", () => {
627
clearTimeout(timeout);
628
});
629
});
630
```
631
632
### Batch Updates
633
634
```typescript
635
function batchUpdates(updates) {
636
return new Promise(resolve => {
637
updates();
638
tick().then(resolve);
639
});
640
}
641
642
// Usage
643
await batchUpdates(() => {
644
count = 10;
645
name = "New name";
646
items = [...items, newItem];
647
});
648
```
649
650
### Reactive Cleanup
651
652
```typescript
653
let resource = $state(null);
654
655
$effect(() => {
656
const signal = getAbortSignal();
657
658
// Create resource
659
resource = createExpensiveResource();
660
661
// Cleanup when effect re-runs or component unmounts
662
signal.addEventListener("abort", () => {
663
resource?.cleanup();
664
resource = null;
665
});
666
});
667
```
668
669
## Types
670
671
```typescript { .api }
672
interface AbortSignal {
673
readonly aborted: boolean;
674
readonly reason: any;
675
addEventListener(type: "abort", listener: () => void): void;
676
removeEventListener(type: "abort", listener: () => void): void;
677
}
678
```
679
680
## Best Practices
681
682
1. **Use tick() for DOM reads**: Always await `tick()` before reading DOM measurements
683
2. **Use settled() for complex chains**: When multiple reactive values might update
684
3. **Use untrack() sparingly**: Only when you truly don't want reactive dependencies
685
4. **Avoid flushSync() in effects**: Can cause infinite loops or performance issues
686
5. **Always handle AbortSignal**: Check `signal.aborted` before state updates in async operations
687
6. **Combine with proper cleanup**: Use abort signals with proper resource cleanup patterns