Svelte provides reactive versions of various built-ins like [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) and [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) that can be used just like their native counterparts, as well as a handful of additional utilities for handling reactivity. ```js // @noErrors import { MediaQuery, SvelteDate, SvelteMap, SvelteSet, SvelteURL, SvelteURLSearchParams, createSubscriber } from 'svelte/reactivity'; ``` ## MediaQuery <blockquote class="since note"> Available since 5.7.0 </blockquote> Creates a media query and provides a `current` property that reflects whether or not it matches. Use it carefully — during server-side rendering, there is no way to know what the correct value should be, potentially causing content to change upon hydration. If you can use the media query in CSS to achieve the same effect, do that. ```svelte <script> import { MediaQuery } from 'svelte/reactivity'; const large = new MediaQuery('min-width: 800px'); </script> <h1>{large.current ? 'large screen' : 'small screen'}</h1> ``` <div class="ts-block"> ```dts class MediaQuery extends ReactiveValue<boolean> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(query: string, fallback?: boolean | undefined); ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `query` A media query string - `fallback` Fallback value for the server </div> </div> </div></div> ## SvelteDate A reactive version of the built-in [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object. Reading the date (whether with methods like `date.getTime()` or `date.toString()`, or via things like [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)) in an [effect](/docs/svelte/$effect) or [derived](/docs/svelte/$derived) will cause it to be re-evaluated when the value of the date changes. ```svelte <script> import { SvelteDate } from 'svelte/reactivity'; const date = new SvelteDate(); const formatter = new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: 'numeric', second: 'numeric' }); $effect(() => { const interval = setInterval(() => { date.setTime(Date.now()); }, 1000); return () => { clearInterval(interval); }; }); </script> <p>The time is {formatter.format(date)}</p> ``` <div class="ts-block"> ```dts class SvelteDate extends Date {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(...params: any[]); ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteMap A reactive version of the built-in [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) object. Reading contents of the map (by iterating, or by reading `map.size` or calling `map.get(...)` or `map.has(...)` as in the [tic-tac-toe example](/playground/0b0ff4aa49c9443f9b47fe5203c78293) below) in an [effect](/docs/svelte/$effect) or [derived](/docs/svelte/$derived) will cause it to be re-evaluated as necessary when the map is updated. Note that values in a reactive map are _not_ made [deeply reactive](/docs/svelte/$state#Deep-state). ```svelte <script> import { SvelteMap } from 'svelte/reactivity'; import { result } from './game.js'; let board = new SvelteMap(); let player = $state('x'); let winner = $derived(result(board)); function reset() { player = 'x'; board.clear(); } </script> <div class="board"> {#each Array(9), i} <button disabled={board.has(i) || winner} onclick={() => { board.set(i, player); player = player === 'x' ? 'o' : 'x'; }} >{board.get(i)}</button> {/each} </div> {#if winner} <p>{winner} wins!</p> <button onclick={reset}>reset</button> {:else} <p>{player} is next</p> {/if} ``` <div class="ts-block"> ```dts class SvelteMap<K, V> extends Map<K, V> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(value?: Iterable<readonly [K, V]> | null | undefined); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts set(key: K, value: V): this; ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteSet A reactive version of the built-in [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) object. Reading contents of the set (by iterating, or by reading `set.size` or calling `set.has(...)` as in the [example](/playground/53438b51194b4882bcc18cddf9f96f15) below) in an [effect](/docs/svelte/$effect) or [derived](/docs/svelte/$derived) will cause it to be re-evaluated as necessary when the set is updated. Note that values in a reactive set are _not_ made [deeply reactive](/docs/svelte/$state#Deep-state). ```svelte <script> import { SvelteSet } from 'svelte/reactivity'; let monkeys = new SvelteSet(); function toggle(monkey) { if (monkeys.has(monkey)) { monkeys.delete(monkey); } else { monkeys.add(monkey); } } </script> {#each ['🙈', '🙉', '🙊'] as monkey} <button onclick={() => toggle(monkey)}>{monkey}</button> {/each} <button onclick={() => monkeys.clear()}>clear</button> {#if monkeys.has('🙈')}<p>see no evil</p>{/if} {#if monkeys.has('🙉')}<p>hear no evil</p>{/if} {#if monkeys.has('🙊')}<p>speak no evil</p>{/if} ``` <div class="ts-block"> ```dts class SvelteSet<T> extends Set<T> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(value?: Iterable<T> | null | undefined); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts add(value: T): this; ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteURL A reactive version of the built-in [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) object. Reading properties of the URL (such as `url.href` or `url.pathname`) in an [effect](/docs/svelte/$effect) or [derived](/docs/svelte/$derived) will cause it to be re-evaluated as necessary when the URL changes. The `searchParams` property is an instance of [SvelteURLSearchParams](/docs/svelte/svelte-reactivity#SvelteURLSearchParams). [Example](/playground/5a694758901b448c83dc40dc31c71f2a): ```svelte <script> import { SvelteURL } from 'svelte/reactivity'; const url = new SvelteURL('https://example.com/path'); </script> <!-- changes to these... --> <input bind:value={url.protocol} /> <input bind:value={url.hostname} /> <input bind:value={url.pathname} /> <hr /> <!-- will update `href` and vice versa --> <input bind:value={url.href} size="65" /> ``` <div class="ts-block"> ```dts class SvelteURL extends URL {/*…*/} ``` <div class="ts-block-property"> ```dts get searchParams(): SvelteURLSearchParams; ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteURLSearchParams A reactive version of the built-in [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) object. Reading its contents (by iterating, or by calling `params.get(...)` or `params.getAll(...)` as in the [example](/playground/b3926c86c5384bab9f2cf993bc08c1c8) below) in an [effect](/docs/svelte/$effect) or [derived](/docs/svelte/$derived) will cause it to be re-evaluated as necessary when the params are updated. ```svelte <script> import { SvelteURLSearchParams } from 'svelte/reactivity'; const params = new SvelteURLSearchParams('message=hello'); let key = $state('key'); let value = $state('value'); </script> <input bind:value={key} /> <input bind:value={value} /> <button onclick={() => params.append(key, value)}>append</button> <p>?{params.toString()}</p> {#each params as [key, value]} <p>{key}: {value}</p> {/each} ``` <div class="ts-block"> ```dts class SvelteURLSearchParams extends URLSearchParams {/*…*/} ``` <div class="ts-block-property"> ```dts [REPLACE](params: URLSearchParams): void; ``` <div class="ts-block-property-details"></div> </div></div> ## createSubscriber <blockquote class="since note"> Available since 5.7.0 </blockquote> Returns a `subscribe` function that, if called in an effect (including expressions in the template), calls its `start` callback with an `update` function. Whenever `update` is called, the effect re-runs. If `start` returns a function, it will be called when the effect is destroyed. If `subscribe` is called in multiple effects, `start` will only be called once as long as the effects are active, and the returned teardown function will only be called when all effects are destroyed. It's best understood with an example. Here's an implementation of [`MediaQuery`](/docs/svelte/svelte-reactivity#MediaQuery): ```js // @errors: 7031 import { createSubscriber } from 'svelte/reactivity'; import { on } from 'svelte/events'; export class MediaQuery { #query; #subscribe; constructor(query) { this.#query = window.matchMedia(`(${query})`); this.#subscribe = createSubscriber((update) => { // when the `change` event occurs, re-run any effects that read `this.current` const off = on(this.#query, 'change', update); // stop listening when all the effects are destroyed return () => off(); }); } get current() { this.#subscribe(); // Return the current state of the query, whether or not we're in an effect return this.#query.matches; } } ``` <div class="ts-block"> ```dts function createSubscriber( start: (update: () => void) => (() => void) | void ): () => void; ``` </div>