Svelte Data Reactivity

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

Rich explains how the Svelte system of reactivity keeps the DOM in sync with the application state, and demonstrates how computed properties work by using declarations, statements, and updating arrays and object properties.

Get Unlimited Access Now

Transcript from the "Data Reactivity" Lesson

>> So, so far all the data that we've used inside these components has been static, it hasn't changed. But a lot of the time when you're building web apps, the data in your components will change. And Svelte has a powerful system of reactivity to make that possible. So first, we're gonna add an event handler to this button.

[00:00:19] And we'll go into more detail about event handlers, what they are and how they work, in a later section of this tutorial. But for now, Just roll with it, on:click= {handleClick}, give it a reference to this function which is defined inside our script block. And then we just need to implement handleClick, and it's very simple, count += 1.

[00:00:43] And now when we click this button, The count clicks up. The way that this works is that Svelte instruments the assignment. When it sees this count += 1, it replaces that in the generated code, which we'll look at in more detail later. The instruments that we just called to a function called invalidate, which tells the component that a specific value has changed.

[00:01:12] The component in turn tells the Svelte scheduler that the component needs to be re-landed. And that is how reactivity works on a per-value level. Now, very often, you'll have some state that is derived from other parts of your state. So we got our button here that increments the counter.

[00:01:37] Let's say we wanna add a double value, which is count * 2. We could do this double = count * 2:, and then add the sign text beneath it, (count) doubled is (doubled). Can't type today. But it's not updating, and the reason for that is that the contents of thid script block execute once when a component is created per component.

[00:02:09] And so this doubled = count * 2, that's just gonna run at the start of the component's lifecycle, and then it's never gonna be rerun. We want that statement to rerun every time the value of count changes, and we can do that with a convenient little piece of syntax.

[00:02:27] Change that let to $:. Now when you click it, It doubles as you'd expect. Now this might look a little bit strange, because this isn't JavaScript syntax, that you're probably familiar with. It is in fact valid JavaScript. This right here is called a label. And it's used when you're building a for loop or a while loop.

[00:02:51] You'd have a label, and then later you can do break label name. And that allows you to control the flow of your application in a way that you generally don't need. Outside the context of the loop, it has no value whatsoever. So when we were building Svelte, we thought, let's just steal that.

[00:03:09] The reason that we have to make everything valid JavaScript is because, as I'll explain later, we're using off the shelf JavaScript parses to parse everything inside here. So everything has to be syntactically valid. But it does not mean that this needs to behave the way that it would ordinarily behave inside JavaScript.

[00:03:27] We get to make the rules. So this here is what we call a reactive declaration. And we can have as many of them as we like. So I can have one that depends on the reactive value of doubled quadrupled = doubled * 2. Add another one of these.

[00:03:56] And that also works as you would expect. And you'll notice, that these aren't defined in the order that they would ordinarily need to run. Instead, they're executed in what's called topological order. Which means that Svelte understands the quadruple depends on the value of doubled. And therefore, it needs to calculate doubled before it calculates quadrupled.

[00:04:16] So this might look a little bit weird and a little bit alien, but I promise you that once you get used to it, it becomes second nature. And it's a very convenient feature And it's not just declarations that we can run reactively. We can also run any arbitrary statement in the same way.

[00:04:34] So for example, we can do console.log {'the count is $count}:. Then you'll see here that it gets logged every time that value changes. So that's really useful for debugging. And you can group statements together by putting them in a block, like so. And it's not even gonna let me type that because it's gonna reevaluate on every chain.

[00:05:07] So I'm just gonna paste the whole thing in. If we change that, we get another alert, and if we change that, another alert, and so on. Please don't do that to your users. And you can even put the $ in front of things like if blocks. I'm just gonna copy and paste that whole lot into here.

[00:05:33] And now when I click it, if we get too high, it'll prevent you from going any further. And it's not just symbol permitted, we can update in this fashion. We can also use the reactivity to update arrays and objects, but there is a caveat which we're gonna explore here.

[00:06:01] So we have this function, Add number, which is gonna push to our numbers array. When I click this button, it's not doing anything, and that's because numbers.push is not reactive. Svelte doesn't look at that and say, we're mutating this array, therefore we need to recalculate anything that involves numbers.

[00:06:19] It needs to see an assignment. That's how the system works. So we can do underneath that numbers = numbers, that's one way of doing it. But it's not very idiomatic, it looks a little bit weird. It's useful in a pinch, but it's actually better if rather than mutating that numbers array and then reassigning it to itself, if we create a new copy of our array, we can do that, like so.

[00:06:50] Print new array, spread the existing value into it, and then add the new value. And now, it updates exactly the same way. And you can use similar patterns to replace shift and shift and splice the other array mutation methods.