DEV Community 👩‍💻👨‍💻

Cover image for How to Handle Reactivity in Svelte
Johnny Simpson
Johnny Simpson

Posted on • Originally published at fjolt.com

How to Handle Reactivity in Svelte

Svelte, like most frontend frameworks, is a reactive language. That means data updates translate straight into UI updates. Let's look at how reactivity works in Svelte.

If you're brand new to Svelte, read my guide on getting started with Svelte here.

Reactivity in Svelte

At its most basic, variables are generally reactive in Svelte. For example, creating a component like this will result in a live updating counter displayed within the button:

<script>
    let x = 0;
    const addToCounter = function() {
        ++x;
    }
</script>

<button id="counter" on:click="{addToCounter}">{x}</button>

<style>
    button {
        background: #ffb334;
        border-radius: 8px;
        border: none;
        font-weight: bold;
        cursor: pointer;
        padding: 0.5rem 2rem;
        color: white;
        font-size: 1.5rem;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Above, x is increased by one every time the button is clicked. We do this with on:click="{addToCounter}". The {x} displayed in #counter is automatically increased and displays the new value on every click.

In that way, Svelte provides reactivity out of the box - so it's really easy to intuitively understand what's going on. Svelte also provides some more advanced reactivity features.

Reactive Calculations

In some scenarios, we want to update a value like x, and then do a calculation on it. We may then display that within our UI somewhere. For example:

<script>
    let x = 0;
    let bigX = x * 2;
    const addToCounter = function() {
        ++x;
    }
</script>

<button id="counter" on:click="{addToCounter}">{bigX}</button>

<style>
    button {
        background: #ffb334;
        border-radius: 8px;
        border: none;
        font-weight: bold;
        cursor: pointer;
        padding: 0.5rem 2rem;
        color: white;
        font-size: 1.5rem;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Above, we want to show our calculated bigX value within the button tag, which should equal x * 2. Upon clicking the button, x will increase by one, and therefore we'd expect bigX to also react.

However, in Svelte this will not work, as calculated values like this aren't inherently reactive. As such, we need to tell Svelte that bigX should also react. To do that, we replace let with $:.

The below code will now update bigX every time x is updated, and display it within our button:

<script>
    let x = 0;
    $: bigX = x * 2;
    const addToCounter = function() {
        ++x;
    }
</script>

<button id="counter" on:click="{addToCounter}">{bigX}</button>

<style>
    button {
        background: #ffb334;
        border-radius: 8px;
        border: none;
        font-weight: bold;
        cursor: pointer;
        padding: 0.5rem 2rem;
        color: white;
        font-size: 1.5rem;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Reactivity Principles in Svelte

Svelte intelligently understands that if $: bigX = x * 2, and we want bigX to be reactive, that it should only update if x is updated.

Reactive blocks in Svelte

In the same way that we can make independent variables run again whenever something within them changes, we can do the same for block statements. For example, let's say we want to check if x is equal to 5. If we write the following, it won't do anything:

let x = 0;
if(x === 5) {
    console.log(`x is ${x}!`);
}

const addToCounter = function() {
    ++x;
}
Enter fullscreen mode Exit fullscreen mode

That's because on initiation, x is 0, and the if statement only runs once. If we want it to run every time x updates, we add $: to the start:

let x = 0;
$: if(x === 5) {
    console.log(`x is ${x}!`);
}

const addToCounter = function() {
    ++x;
}
Enter fullscreen mode Exit fullscreen mode

The same can be done with curly bracket block statements alone. For example, the below code console logs x any time it changes:

let x = 0;
$: {
    console.log(x);
}

const addToCounter = function() {
    ++x;
}
Enter fullscreen mode Exit fullscreen mode

Out of all the frontend frameworks, Svelte perhaps makes reactivity the most easy. If you've enjoyed this article, you can find more Svelte content here.

Top comments (4)

Collapse
peerreynders profile image
peerreynders • Edited on

Svelte perhaps makes reactivity the most easy.

import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [x, setX] = createSignal(0);
  const bigX = () => x() * 2;
  const addToCounter = () => setX(x => x + 1);

  return (
    <button type="button" onClick={addToCounter}>{bigX()}</button>
  );
}

function Style() { 
  return (
    <style>{
      `button {
        background: #ffb334;
        border-radius: 8px;
        border: none;
        font-weight: bold;
        cursor: pointer;
        padding: 0.5rem 2rem;
        color: white;
        font-size: 1.5rem;
      }`
   }</style>
 );
}

render(() => <><Style/><Counter /></>, document.getElementById("app"));
Enter fullscreen mode Exit fullscreen mode

Playground

Cobbled together by peeking at

other than that I haven't used Solid.js a lot (I've spent considerably more time with Svelte). Really the most magic here is that x() in bigX tracks bigX() invocations and updates them whenever setX() is executed.

(The big difference to React is that Counter only runs once to set everything up - past that it just plain reactivity.)

Svelte adds reactivity by extending the language with reactive declarations and statements (and lets not forget about stores (Solid's stores)).

Collapse
smpnjn profile image
Johnny Simpson Author

I guess it ultimately comes down to personal preference!

Collapse
1coma21 profile image
1coma21

Svelte should have been called react

Collapse
smpnjn profile image
Johnny Simpson Author

maybe it should be called reacte

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.