Check out a free preview of the full Svelte Fundamentals course
The "Logic" Lesson is part of the full, Svelte Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Rich discusses using logic to render HTML conditionally, including if, else, else-if, each, keyed each, and await blocks. How race conditions are handled, and student questions regarding if "each" is a reserved keyword and what happens if the keys aren't unique.
Transcript from the "Logic" Lesson
[00:00:00]
>> Let's talk about logic. HTML does not have a way of expressing logic, like conditionals and loops. Svelte does. If you wanna conditionally render some markup, we can wrap it in an if block, which looks like this. Let's add some text that appears when the count is greater than 10.
[00:00:21]
So after the button, open the curlies, add a hash, if count is greater than 10, Close that, then we'll add some text that says count is greater than 10. Now, if we click the button enough times, lo and behold, the text appears. Just like in JavaScript, an if block can have an else block.
[00:00:54]
So in this case, if the count is not greater than 10, then we know that it is between 0 and 10. So let's add that into app.spell down here. This time, we're gonna use a colon before the else. And inside there, counts is between 0 and 10. Zero is between 0 and 10.
[00:01:19]
1 is between 0 and 10. All the way up to 10 is between 0 and 10. And then we switch into the other half of the block. Okay, so let's talk about the syntax here. When you have plain curlies, that is just enclosing a JavaScript expression. When you have the hash symbol or the pound symbol, that is opening a block an if block or an each block and there are other kinds of blocks.
[00:01:44]
When you have a colon, it is continuing that block. It's opening a new section. And then when you have the slash just like with the HTML element and you have the angle bracket followed by the slash, that is closing the block. So that's a lot of syntax to learn in one go.
[00:01:57]
But the good news is you basically learn all of the syntax that Svelte inflicts upon you at this point. And you can chain multiple conditions together with an else if. Let's have an intermediate step where count is less than 5. Else if count is less than 5, oops, a little typo there.
[00:02:36]
And then we just need to update that bit at the bottom, and we click that. We're now switching between the three branches of this if block. All right, now when you're building user interfaces, very often, you will find yourself working with lists of data. In this exercise here, we've repeated this button markup multiple times.
[00:03:03]
You've got a button for the red, we've got a button for the orange, and then we've got a button for the yellow. But after that, I just got tired and I added a to-do. We've still got more colors to add, we've got an entire rainbow to show here.
[00:03:16]
So instead of copying and pasting and editing each of these, what we can do is we can render those buttons in a list. So let's get rid of all but the first button, get rid of those like so. And then we'll wrap the remaining button in an each block.
[00:03:37]
So again, we're using the hash key to open a block, and the syntax is each colors. And we get a name to it as color, like so. And then we'll close that after the each. And so you can see now it is iterating over this colors value here, which includes everything in the rainbow.
[00:04:00]
But it's rendering red each time, which is not much help. We wanna change that to use the current color in each iteration. So we'll just replace all of the red occurrences. Tip, if you do command D, then you can select multiple selection ranges at once. So because I've selected this red string here, and then I press command D.
[00:04:26]
I can select both of these, and edit them simultaneously. The ARIA label also needs updating, that's for people with vision impairments. And then, background will replace that with the actual value, and you'll see that our user interface is starting to take shape. You can get the current index inside an each block as a second argument by adding it here.
[00:04:55]
We'll call it i, fairly conventional. And then inside the button, we'll reference i+1. Right, and so now we have numbers to go along with the styles. If we press these, you'll see that we're actually updating the selected value. So you can use that inside the Markup, but you can also use it inside the Event Handler, which is what's happening here.
[00:05:24]
When we click it, we're assigning the current color inside the loop to the value of selected. All right, this one is a little bit of a tricky thing to wrap your head around at first, but hopefully, it'll become clear. By default, when you modify the value of an each block, it will add and remove items at the end of the block, and update any values that have changed.
[00:05:54]
So let me show you what I mean. In this exercise, we have an each block. We're iterating over this things array, which looks like this. Each one has an ID and a name. And then inside the thing component, we're matching the name to the corresponding emoji. And we're assigning that value when the component is first created.
[00:06:22]
So we're linking the apple emoji to the apple text, the banana emoji to the banana text, and so on. But watch what happens when we start removing things from this array. If we remove the apple, then the text apple goes away, but the emoji apple is still there.
[00:06:40]
And the reason for that is that we haven't got rid of the first component. We got rid of the last component, but we're now passing the new text into the remaining components. But inside thing.svelte, we assigned this emoji when the component was first created. If you use things like React, that might be a little bit surprising because in those frameworks, things update every time you render.
[00:07:06]
In Svelte, we don't do that. Svelte is deliberately designed in a way that makes it more efficient to update the content of the DOM. So one way that we could fix this is we could turn this into a reactive variable. We could replace this const with $:.
[00:07:27]
And now should remove things, it'll update the value of emoji at the same time as the new name is being passed in because it sees that it depends on that changing name. But that's actually not what we want. What we want is to remove the first component instead of removing the last component and updating all of the rest.
[00:07:49]
And to do that, we use something called a keyed each block. What this means is that we, let me just get rid of that, replace it to how it was. What this means is that inside each block, we're gonna assign each iteration of that loop a key that will be used to figure out which component needs to be removed.
[00:08:11]
And the way that we do that is by putting some unique value inside parentheses. We use thing.id. A little call out here, we're using thing ID which is a number but you can actually put any value in here. It's using map internally so you can use objects, you can use whatever it is.
[00:08:32]
As long as when that data changes, it can compare the new list with the old list and figure out what's been added and what's been removed. So now if we click the button, remove the first thing, it's getting rid of the first component in its entirety.
>> Is the keyword each a reserved keyword in Svelte?
[00:08:52]
>> It is reserved when you have the hash symbol. You have a curly followed by a hash, that has to be followed by if or each or a await or key, which we'll learn about in a second. But if you're not building a block, then you can use it wherever you like.
[00:09:08]
So you can use the word each for whatever it is you're building. You can't use the word if or the word await, because those are JavaScript keywords, but each is not a JavaScript keyword, so that's up for grabs. You can use that however you like.
>> What happens if the key is not unique?
[00:09:27]
>> The key is not unique, then things will break, essentially. I actually can't remember off the top of my head it will throw an error or if it will just bulk up your application. I would need to check. The moral of the story is don't do that. Make sure that you are using unique keys in your keyed each box.
[00:09:47]
Otherwise, unexpected things will happen and you have a mess to clean up. Grant.
>> In the example here, if you make the keys not unique, it just doesn't render anything.
>> Yep, just doesn't render anything. Okay, there you go. So there's the answer. You need to have unique keys, otherwise, it's gonna get very confused.
[00:10:02]
All right, let's talk about async data. Most web applications are gonna need to deal with async data at some point. And in Svelte, you can use async values directly in your markup by using an await block. So in this exercise, we've got a button that generates a random number.
[00:10:22]
And it's actually fetching from a URL that you can't see in this exercise. But it has an artificial delay attached to it, so that it'll take a minute for that promise to resolve. And sometimes, it won't resolve, sometimes it will reject instead. So we could get random number, we have a promise.
[00:10:43]
We wanna use that inside our markup. We can do so by wrapping this content in an await block, as before, curly brace hash, followed by the type of block. Gonna await the promise and then we'll add a then section, sorry, then number, so that we can refer to the resolve value of the promise.
[00:11:09]
We'll then add a catch section and give the caught error a name. And then we'll close the await block. And so inside this middle section, the then number section, you can see it's giving us a warning that we have an empty block, so we need to put some content in there.
[00:11:27]
Create a paragraph, the number is number. And then when we catch an error, we'll put a paragraph there as well. Style equals color red, color of danger. And we'll just print the error message that was caught. Okay, and you'll see that we got an error this time, the request failed and so we're now printing that to the page.
[00:12:04]
Try it again, fail again, try again. Finally, we got a random number, 29. So only the most recent promise is considered at any time. So if you spam this button, you don't need to worry about race conditions. In some cases, you might know that your promise cannot reject.
[00:12:25]
You should generally add a catch block, but you might be able to guarantee that the promise is gonna succeed. And in that case, you can get rid of the catch block altogether. And in some cases, you might not need to show any user interface while we're waiting for that promise to fulfill.
[00:12:43]
And so in those cases, we can get rid of everything except that, await.promise then number, and we show the number. The number is 9.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops