Check out a free preview of the full Vue 3 Fundamentals course
The "Composition API" Lesson is part of the full, Vue 3 Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Ben discusses that composition API, when used with Vue, is vanilla JavaScript and allows custom code organization at the cost of having no default option. A brief overview of the experimental feature Suspense and a demonstration of rendering data from an API is also covered in this segment.
Transcript from the "Composition API" Lesson
[00:00:00]
>> Alright, we're here, took us a little while, but we're here at composition API. And it's time to talk about the brand new thing that is with view three. The first thing I want to caveat when it comes to the composition API is that even though it was introduced in view three, there actually are ways to use it on view two.
[00:00:14]
So that is one of the things that the team has tried to work really hard on is that,even though there are certain performance optimizations and sort of like type Script enhancements that have come with view three. As a whole, when it comes to feature parity, the team has actually worked really hard to try to keep it as basically cross compatible as humanly.
[00:00:31]
Be possible because they know, a lot of times people when they're working on enterprise apps, as much as developers would love to be on the cutting edge tool ,the reality is that most of time there's just no time to do that. And so rather than have developers be kind of feeling left out of the fact that they might want to rewrite their components using composition API.
[00:00:49]
We basically have plugins that allow you to plug in the composition API interview too. So again, while this is a view three feature, just know that you can use this in view two, you just need to look into the plugin. All right, so, composition API, let's talk about it.
[00:01:04]
So remember this lifecycle, diagram that we talked about earlier? Up here, you'll notice in blue, there's a very special lifecycle hook. That's called setup. And so setup has a very special meaning for us in view because why? Anytime you basically see the setup keyword, the lifecycle hook, you're basically ensured that you're using composition API.
[00:01:24]
I think that's one reason why the diagram here actually has it in parentheses. This is because as we can see here, prior to the setup function, there is nothing else. So this is what's interesting with the composition API is that it happens before the options API. So what does that really mean?
[00:01:41]
So we take a look at our code. I'm not hoping into the playground, so that we can just kind of code some stuff without messing up Scylla view, go into the playground. And then NPM run Dev. Boom, okay, we have a Pokedex ACC app and it's running. Alright, so let's go ahead and see what is going on here.
[00:02:04]
For whatever reason, it did not open it. The actual folder,there we go. Okay, so close this,close this, we're in playground right now. If we take a look at our app dot view, you'll notice here that we're running a fetch and we're doing all this stuff inside of created.
[00:02:23]
Now, I mentioned that the set of function actually happens before and knit. So actually if you think about asynchronous, they really should be run in the setup function, because that's its earliest point of starting sort of like the component lifecycle. So how that might look is that we, actually would have a setup function that's up here at the top.
[00:02:43]
And the reason I think it's important to organize your code this way and putting set up at the top is because everything else below does not exist. And it's useful to kind of think of it this way Is that this is what I'm doing inside of here. Now the thing that makes the composition API particularly unique when it comes to view is that everything inside of here is truly vanilla JavaScript.
[00:03:04]
So in other words there's, we can't just go like data, function, return, Pokedex like all this stuff is gone because why,composition API is about I guess some call it freedom and flexibility. One of the advantages of options API is that, it provides a very consistent way for you to add stuff.
[00:03:24]
Here's where my data goes, here's where my methods go, here's where my computer properties go. But over time, as people have scaled their applications and components, there are times where people found that they wanted to actually group things according to their concerns. And maybe find ways to organize their codes in different ways.
[00:03:38]
The composition API lets you do that. But what that means though, is that it's a free for all in that you have to organize everything yourself. So in the instance of setup, let's have a reactive named variable, in this case for the region of Pokemon that this is tracking.
[00:03:54]
So the first thing is to remember this is vanilla JavaScript so we actually have to declare the variables manually now. So, const, region name equals kanto, great. Now here's the thing though, when we actually look at this. So, let's look inside the Dev tools, and look at our app.
[00:04:15]
We'll see here that nothing exist right now, only the Pokedex is showing up. And the reason for that is because once you're inside of setup view, is not doing any magic for you, you have to actually start being very explicit about what's happening. So the thing about the composition API is that inside of here, view is not doing any magic for you.
[00:04:34]
So unlike when we're inside the data and methods where you can just call this context and it knows to like this. That Pokedex knows to go inside of data to go get the Pokedex, like, inside of here, everything is like, okay, you want the freedom here's freedom. And so what does that mean?
[00:04:49]
That means that at the end of setup, we actually have to manually return anything we want to expose. And at first, that might sound a little bit redundant, right? You're like, wait, why would I want to do that? Well, because what you'll see now inside the Dev tools is that, check it out, the region name is appearing.
[00:05:05]
And the reason for that is because when you're writing the JavaScript up here, you probably don't want everything being exposed to your component. There are times certain things might be called private, and there are things where you're running calculations that aren't relevant to the template and to the rest of the component.
[00:05:18]
And so that you can keep all up here. And what you're doing here is that you're returning it. And so when you return it now it's actually something that you can actually access. So let's say inside of this created method, now it can be like log, this dot region name.
[00:05:35]
And so we'll see now inside of here, there you go. The created lifecycle hook now has access to the data that we set up inside of setup. Didn't mean to do that, but that's how it worked out, okay. So the question here is, I want the ability to run an async function at this point, right?
[00:05:55]
And so your first instinct might be like, well, okay, this makes sense. What we're gonna do here is we're gonna create a, Const of Pokedex, and we'll just copy over this await function and then we'll just make sure that setup is async because this isn't a await. And then we'll return the Pokedex here and let's keep that actually alphabetical.
[00:06:21]
And then since we're returning it anyways, you don't need to define the data twice, so there we go. And then we actually don't even need this method anymore, right? Cause we've just refactored it. And then, we're running this inside of here. So actually now that I think about it, we could just say, we just need to delete this and then ideally we could then just say this dot Pokedex.
[00:06:45]
So we just see the region name and the Pokedex show up but you're gonna see view yelling at you in a pretty big way. And I wanted to show this error because most of the time this is not gonna be something you run into but especially when you're getting started and you see this error it's probably gonna be a bit confusing.
[00:07:02]
Because you're gonna look at this and if we read it, it says that set a function returned a promise, but no suspense boundary has been defined and that's a lot of words, right? You're like what the heck is going on? Well, so just to let what is suspense?
[00:07:15]
So we look inside of the docks. Suspense is another built in component that is experimental currently with view. And the idea behind this is that, it's trying to help us better offload performance when it comes to asynchronous option. So in the sense of like when you're loading something asynchronously, you can have a fallback.
[00:07:33]
So the way that code works as you can see here, is that you can see here, so you would drop in your suspense component. And okay, this is my dashboard that I'm loading a bunch of async stuff happening, but in case that fails, or frankly, it's not ready for me yet, I'm gonna go ahead and fall back to this template.
[00:07:54]
This syntax should look familiar to you, because earlier, we talked about slots. And so here's that V slot fallback. And this is already defined on the suspense component. And so what you'll end up seeing on the pages you'll see loading first, and whenever it's ready, view will automatically switch it over to the dashboard.
[00:08:13]
And so this is actually really useful. But the key thing here though, to understand though especially at this point in the recording, is that it is experimental. So this is why at this moment we're not gonna go into depth regarding how to use it and that kind of thing.
[00:08:24]
Keep an eye on the dock if you wanna play around with it, but know that this will probably be a pretty key part of a lot of framework approaches going forward. As a lot of frameworks are trying to figure out better ways of server-side rendering different things, and how to improve performance when it comes to loading JavaScript on a page and so forth.
[00:08:42]
Now, when it comes to our error though, the reason this is a problem at this particular point in time is because if we think about it from the tree itself, the app dot view is the root component of everything. So you can really suspend your root component in a state of nothingness, that does not work.
[00:09:03]
And so what you actually have to do is that, in the case that you really do need to do asynchronous operations in composition API. This is where you need to put it into a component, because the app dot view basically needs to be in a stable state. That's like, Okay, I know where everything is and then this component over here is going to do some stuff.
[00:09:17]
I'm gonna hang on to it and give it a backup. And then I can do other stuff over here. But we spend app dot view the whole thing, basically, because of how asynchronous operations work, it just runs the risk of corrupting it right? So this is why we don't run async setup at the root level at app View.
[00:09:33]
So to show how this works then is, we're gonna go ahead and create a component called Pokedex. And this is where we're gonna go ahead and then we'll have our script tag and we'll have our template, if it would auto complete sometime Emette is uncooperative with me. Okay, great.
[00:09:54]
So let's go ahead and blow this up into two columns, so that's easier to follow. We'll go ahead and bring over this asynchronous request right here. Actually, we can bring over the whole script blog. What am I talking about? Bring over the whole thing, which is great. And then this means that this script block is actually no longer needed on this app.
[00:10:15]
Otherwise we do need a script block because why, we need to import our Pokedex. So Pokedex from components Pokedex Dot View, and then we can register it on the components. And then we have Pokedex like that.
>> We've got a case mix-up in the--
>> We have a case mix-up?
[00:10:38]
With you, I did that again. Thank you for catching that. This is sometimes the trouble with the context switch. Okay, so inside of here, we'll have our template here for the pre-fetch. We don't even need this anymore, this button. So all this is gonna do is render that as a pre block and mean we can take this here and then we get the Pokedex like this okay.
[00:11:01]
So let's take a look and see if this worked out the way we wanted it to, okay. So, first thing first, we'll see that when we're taking a look at this right now, it's still yelling at us, but we actually are seeing something rendered unlike before. And it's because in this particular case, it's true we still need to actually suspense Component at this point.
[00:11:23]
And so like I said, we're just going to cover a high level uses of it. We're not going to dive deep into suspense as a component. Because again, if we think about it from a view perspective is that view, is saying, I don't know what to do with this yet.
[00:11:34]
So please give me some sort of fallback so that in case this thing completely crashes, we don't have this hanging component that's not going to do anything. So we bring in our suspense component. And we say, Okay, this is what I want you to render. But in case things don't work, here's the fallback where we say loading Pokedex data, just like that.
[00:11:57]
Suspense, suspense, suspense ,bom bom. Yes, I already know that, okay. So why? Let's restart the server real quick, just to make sure that's not anything weird getting botched.
>> You don't have to import suspense?
>> No import, It's kind of like the global component. It's just a global component that's registered.
[00:12:22]
Now What's weird? I forgot, yeah. Okay, so inside of here you're thinking I did the suspense right, right? I did it inside of my component because I gave it a fallback. But this approach doesn't work because if we think about it another way, it's happening at the child level.
[00:12:40]
And if we look at the error messages again, it actually says that the suspense boundary needs to be found at the parent tree. Because if you think about it another way, remember how we used to do the VF? This is the same kinda concept where you want the VF actually happening at the top for something like suspense, because it knows what to handle.
[00:12:56]
So, if I go ahead and delete this stuff again,this time we can actually say we'll have a suspense component here. That will then render out the Pokedex component when it's ready otherwise fallback to this text that's actually what's happening here. And once we do that, now everything is working as expected.
[00:13:16]
So again the API for suspense is experimental but this mental model now of having the ability to suspend your component and then have it switch out with some sort of fallback is something that is going to be more popular with frameworks, not just view. And so something that I wanted you all to keep in mind when it came to that.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops