Check out a free preview of the full Svelte Fundamentals course

The "Reactivity" Lesson is part of the full, Svelte Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Rich demonstrates reactivity in Svelte, keeping the DOM in sync with the application state by building an event handler with an increment function. Reactive declarations, grouping statements, and updating arrays and objects are also covered in this segment.


Transcript from the "Reactivity" Lesson

>> Now we're gonna move on to some of the fun stuff that makes Svelte really enjoyable to use. At the heart of Svelte is a powerful system of reactivity for keeping the DOM in sync with your application state. So when the user interacts with your application, the state will change.

We want the view of that state to change in response. So we haven't learned about event handlers just yet, but we will soon. For now, I just want you to add the on:click = increment code to the button in App.svelte. And what that's telling us is that when we click this button, it will call this increment function.

But we haven't done anything inside the increment function yet, so we need to wire that up. Inside here, we're gonna change the value of count. And the way that we're gonna do that is just by assigning to it. We're not using an API for this. We're not using a set state or something like that.

We're just assigning to the variable. And the compiler can see that and it'll instrument your code in such a way that says, we need to re-render specific parts of this component. And it will do it as efficiently as it can. And so now when we click this button, you'll see that the number does, in fact, increment.

>> Someone's saying they love the new Vim key bindings.
>> [LAUGH]
>> Question mark vim=true.
>> Yeah, okay, so a little aside, you can use Vim mode in this tutorial if you're a Vim fiend. All you need to do is add vim=true in the URL bar. And now, when you select things in the editor, you're in Vim mode.

So I can replace this, I think I have to do with cw clicks, or something like that, then I can replace the entire word. I don't know Vim. If you wanna learn Vim, Frontend Masters has a great course with ThePrimeagen. I recommend that, but I'm not a Vim guy.

So I'm gonna go back to the safety of vim=false. It will remember your setting. You don't need to add the query string each time. And now we can move on to reactive declarations. Okay, so we've seen that if you reference a reactive variable like count directly in your markup, it will update.

But there are oftentimes when you're building user interfaces that you will have something that depends on a reactive variable. So for example, you might wanna track the doubled value of count. And in Svelte, we have a concept called reactive declarations, and they look a little bit funny. They look like this, $: doubled = count.

Now, there's a callout here that says this might look a little alien. This is, in fact, valid JavaScript. That dollar is a syntactical construct called a label. And it's something that you use when you're using for loops and while loops. It allows you to break out to a specific part of your code.

It's not useful in most parts of your code. It's only useful when you're dealing with for loops. And so it's kinda like a free piece of syntax. It's just lying around without much to do. So on the Svelte team, we said, well, why don't we co-op this? Why don't we use this to declare a value that reactively updates when anything that it depends on changes?

So what happens here is the compiler looks at that statement, doubled = count. So I need to add the times 2, otherwise, it's not much use. And it sees that the value of doubled now depends on the value of count. So whenever the value of count updates, the value of doubled will also update.

So we can now use that inside markup. After the button, we'll add a new element, a paragraph, and we'll say count doubled is doubled. Now, if you click the button, does anyone wanna take a wild guess as to what's gonna happen? 1 doubled is 2, 2 doubled is 4, and so on.

Now you could, of course, just write count * 2 here because you can use arbitrary JavaScript inside these expressions. But you might find there are cases where you are using that value in multiple places or you need to have other things that depend on the value of doubled.

And so reactive statements are valuable in that context. And we're not just limited to having values that update reactively. We can also have statements that run reactively. As an example, if I console.log, the count is the value of count. If I open this in a new tab and open the console, get rid of all the junk that appears, click this and you'll see that it is logging the value of count every time I click the button.

And you can group statements together using a JavaScript block. We can add some more text here. This will also be logged whenever count changes. Right, and this now forms a group. Again, we'll open the console, clear it out. And it's executing the entire block of code whenever anything that's referenced inside that block of code is reactively updated.

Okay, so you can even use the dollar label with things like if blocks. You can say that if the count is too large, say, it's larger than 10, It'll reset it, but we'll also say, That the count is dangerously high. Now if we click this enough times, we'll get an alert, warning is that we're clicking the button too often.

So far, we've been dealing with updating simple values like numbers. But because Svelte's reactivity is triggered by assignments, in other words, the compiler is looking for you saying count plus equals 1 or count equals 0. Using array methods like push and splice will not automatically cause updates. So here we have an application where clicking this button will cause this addNumber function to run.

And we're pushing a number to the array using numbers.push. Now, the compiler doesn't know that it's supposed to do anything after that, cuz it doesn't actually know what numbers is it, could be anything. And so we need to tell the compiler that anything that depends on numbers is now out of date and needs to be updated.

So one way to fix that would be to add an assignment that would normally be redundant. We'll do numbers = numbers. And now when we click the button, the compiler knows what's supposed to happen and it will start adding things in that array and rendering the markup correctly when we do so.

Obviously, that's a little bit weird. Assigning a value to itself is not very idiomatic JavaScript. It's totally fine, but if you prefer to do something that is more idiomatic, then you can use an immutable data structure instead. You can copy the array and then append the new value to it instead.

So what that would look like is get rid of the numbers.push and the numbers = numbers, and we'll instead assign to numbers. First, copy it using spread syntax. And then we'll add, The value at the end, like so. And this works as before. The difference is that we're now generating a whole new array every time we press this button.

Now this can be good or bad, depending on what you're trying to do. Working with immutable data has some benefits. It means that you're not gonna run into problems where two things are mutating the same object at the same time. And one of them isn't expecting the other one to mutate it, and mutation is at the heart of a lot of bugs in programming.

But immutable objects are more expensive. If you're creating a new array every time, then you're allocating more memory. And it's not gonna be a problem in a simple case like this, but copying arrays is generally going to be slower than mutating them. So Svelte lets you do both.

It lets you pick the approach that makes sense in the context of your application. It's not gonna enforce that you use immutable data like some frameworks. We can also assign directly to properties of arrays and objects. So plus equals 1 or array[i] equals x. Those will work the same way as assigning to the values themselves.

So another way that we could solve this problem, this is gonna mutate the array, but also using an assignment is numbers.length = numbers.length + 1. And again, it works correctly.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now