Skip to main content

Svelte's reactivity not only keeps the DOM in sync with your application's variables as shown in the previous section, it can also keep variables in sync with each other using reactive declarations. They look like this:

ts
let count = 0;
$: doubled = count * 2;

Don't worry if this looks a little alien. It's valid (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'. Once you get used to it, there's no going back.

Let's use doubled in our markup:

<p>{count} doubled is {doubled}</p>

Of course, you could just write {count * 2} in the markup instead — you don't have to use reactive values. Reactive values become particularly valuable when you need to reference them multiple times, or you have values that depend on other reactive values.

App.svelte
<script>
let count = 0;

function handleClick() {
count += 1;
}
</script>

<button on:click={handleClick}>
Clicked {count}
{count === 1 ? 'time' : 'times'}
</button>

/* App.svelte generated by Svelte v4.2.19 */
import {
SvelteComponent,
append,
detach,
element,
init,
insert,
listen,
noop,
safe_not_equal,
set_data,
space,
text
} from "svelte/internal";

import "svelte/internal/disclose-version";

function create_fragment(ctx) {
let button;
let t0;
let t1;
let t2;
let t3_value = (/*count*/ ctx[0] === 1 ? 'time' : 'times') + "";
let t3;
let mounted;
let dispose;

return {
c() {
button = element("button");
t0 = text("Clicked ");
t1 = text(/*count*/ ctx[0]);
t2 = space();
t3 = text(t3_value);
},
m(target, anchor) {
insert(target, button, anchor);
append(button, t0);
append(button, t1);
append(button, t2);
append(button, t3);

if (!mounted) {
dispose = listen(button, "click", /*handleClick*/ ctx[1]);
mounted = true;
}
},
p(ctx, [dirty]) {
if (dirty & /*count*/ 1) set_data(t1, /*count*/ ctx[0]);
if (dirty & /*count*/ 1 && t3_value !== (t3_value = (/*count*/ ctx[0] === 1 ? 'time' : 'times') + "")) set_data(t3, t3_value);
},
i: noop,
o: noop,
d(detaching) {
if (detaching) {
detach(button);
}

mounted = false;
dispose();
}
};
}

function instance($$self, $$props, $$invalidate) {
let count = 0;

function handleClick() {
$$invalidate(0, count += 1);
}

return [count, handleClick];
}

class App extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}

export default App;
result = svelte.compile(source, {
generate:
css:
});
/* Add a <style> tag to see compiled CSS */