Amazing Svelte reactive statements. With code examples and images.

Have you been asking yourself what exactly reactivity in Svelte is? How to trigger reactivity for arrays mutation, what exactly does this weird $: syntax actually mean and how to reflect changes immediately after the store’s value changes?

If some of the answers are yes then I’m inviting you to find the answers to these questions together with me today!

Reactivity in Svelte allows you to reflect the changes of your component state with a simple assignment operator (i.e. “=”) without any reference to a boilerplate code.

In this article, I’m getting acquainted with Svelte reactivity. I’ve prepared a few code snippets and images that I’ve included in this article to better explain the concepts so please, join me in this investigation.

If you are in a hurry and what to find the quick answer then consider reading the following sentences:

Reactivity in Svelte means that when your component’s properties change the results are immediately reflected in the HTML after you assign a new value to the variable (name = “Mr. Cool”). The simplest way to trigger reactive change when mutating arrays with methods like “push” is just to re-assign the array e.g. array.push(‘new’); array = array.  $: marks a statement as reactive meaning the statement will be called every time a dependent value is changed e.g. $: document.title = title. To make a store value reactive just add a $ before the store’s variable name.

Here is the main structure of the article:

  • Svelte reactivity with a simple “=” operator
  • Svelte reactive statements with $:
  • Svelte reactivity for stores

Check my Github repository to find the code for example components from this article.

Tell me when you are ready and let’s start!

Svelte reactivity with a simple “=” operator

I often try to find the easiest way to deal with a task, as probably you are.

When it comes to updating the HTML based on your component’s state what can be easier than just to assign a value to a variable and see the change in HTML?

Let’s see the example where I don’t implement any additional logic to sync the HTML with the components state but Svelte does all the hard work instead of me.

Clicker app demo
<script>
    let count = 0

    const handleIncrement = () => {
        count += 1
    }
</script>

<h2>You've clicked {count} times</h2>
<button on:click={handleIncrement}>Click</button>

What I used is just the assignment operator, but received sync between the component’s state and HTML. Feels incredibly natural and neat, isn’t it?

Svelte has this feature out of the box. You don’t have to do anything special (except using assignment operators, of course) to make it work.

There is a caveat when you deal with array mutation method like push though.

Svelte’s reactive is based on the assignment operator meaning that when you call a method like push Svelte doesn’t know that the value changed.

Let’s see the example of how we can deal with this issue:

<script>
  const arr = [1, 2, 3]

  // This won't work. After clicking the button you would still see 1,2,3
  const addFour = () => arr.push(4)

  // This should work as expected
  const addFourReactive = () => {
    arr.push(4)
    // Assignment operator
    arr = arr
  }

  // This should work as expected and is a preferable option
  const addFourReactivePreferable = () => {
    arr = [...arr, 4]
  }
</script>

<p>{arr.toString()}<p>
<button on:click={addFour}>Add four</button>

The step of re-assigning the array is completely redundant from logic perspective, but it does what do we need and I think it can come in handy in a specific situation.

In other situations, we should stick to the idiomatic option as mentioned in the Svelte tutorial.

Svelte reactive statements with $:

Sometimes, you need your component properties to be computed from values in your current app state and sometimes you want to debug the exact value of the variable after it has changed.

Svelte has a $: syntax to help us with these tasks. It marks the statement as reactive and calls it each time whenever the values that they depend on have changed.

Let’s consider the example where I update my app’s title each time the input changes its value. I have also included a reactive console.log statement to make this example more demonstrative.

Reactive title change example
<script>
  let title = 'An old good title'
  
  $: {
    document.title = title
    console.log(title)
  }

  // or like this
  // $: document.title = title
  // $: console.log(title)
</script>

<h2>Change that title!</h2>
<input type="text" bind:value={title}>

Due to Svelte’s documentation you can’t make a statement inside a function or inside a block reactive using $:.

Any top-level statement (i.e. not inside a block or a function) can be made reactive

https://svelte.dev/docs#3_$_marks_a_statement_as_reactive

It means that the following code won’t work as expected:

<script>
  let title = 'An old good title'
  
  if (title === 'my title') {
    $: document.title = title
    $: console.log(title)
  }
</script>

To make it work properly we would need to implement something similar to this:

$: if (title === 'my title') {
  document.title = title
  console.log(title)
}
Conditional reactive statements example

$: is not a specific syntax for Svelte. As documentation claims the behavior is based on using the JS labeled statements that you can use in any Javascript app.

I’ve tried to dig a bit deeper to find out how exactly Svelte achieves the desired effect using JS labels, but haven’t found any suitable information to share yet.

From what I’ve seen already it seems that for efficient use of JS labels there should be a labeled loop.

I assume that Svelte uses a loop somewhere in the external logic to successfully mimic the “goto” functionality, but these are just my guesses yet.

Svelte reactivity for stores

Sometimes you need to share the state with multiple components in various places in the application and the stores may be very useful for this purpose, but how to make the store values reactive to be able to reflect them immediately in HTML?

Let’s consider the example where the value of the store reflects immediately in HTML after the store’s value changes.

Store reactivity app example
<script>
  import count from '../stores/count'
  import Increment from './Increment.svelte'
</script>

<h2>The current values is: {$count}</h2>
<Increment />
// Increment.svelte

<script>
    import count from '../stores/count'

    const handleIncrement = () => {
        count.update(count => count + 1)
    }
</script>

<button on:click={handleIncrement}>Increment</button>
// stores/count.js

import { writable } from 'svelte/store'

export default writable(0)

Alternatively, count store could have an object as a value:

<script>
  import count from '../stores/count'
  import Increment from './Increment.svelte'
</script>

<h2>The current values is: {$count.number}</h2>
<Increment />
// Increment.svelte

<script>
    import count from '../stores/count'

    const handleIncrement = () => {
        count.update(({ number }) => ({ number: number + 1 }))
    }
</script>

<button on:click={handleIncrement}>Increment</button>
// stores/count.js

import { writable } from 'svelte/store';

export default writable({ number: 0 });

As you can see I had to just add a $ before the store’s name to make the store’s value reactive.

Any time you have a reference to a store, you can access its value inside a component by prefixing it with the $ character. This causes Svelte to declare the prefixed variable, and set up a store subscription that will be unsubscribed when appropriate

https://svelte.dev/docs#4_Prefix_stores_with_$_to_access_their_values

If for some reason you don’t need a store you can use the same syntax for a plain object that successfully implements a store contract.

You can read about the store contract in Svelte’s documentation.

Conclusion

A simple assignment operator and a few $ to update primitives, objects, and stores. It is incredibly easy to achieve reactivity in Svelte’s applications, isn’t it?

I hope you found the answers to some of your questions and learned something new about Svelte reactivity with me today!

We’ve implemented a few example apps that help to solve a few tasks, here they are:

  • Reflect the changes immediately after the component’s state changes
  • Make a document.title update and console.log statements reactive
  • Implement a conditional reactive statement
  • Reflect the changes in the store’s state change when the value is a primitive or an object

What next?

You might want to check this Svelte’s reactivity tutorial to wrap your head around the concepts and have some practice without the need to set up your own application.

If you like this article maybe you will be interested in reading my previous articles Svelte with Typescript. Make it possible with Webpack and Svelte hot reloading. With Webpack or Rollup.

You can support me by sharing your feedback about this article with me at letconstportal@gmail.com