Check out a free preview of the full Vue 3 Fundamentals course:
The "Composables" 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 demonstrates a type of reusable JavaScript utility to share props between components called composables that similarly utilizes the use prefix from React. A walk-through of implementing composables in the base counter is also covered in this lesson.

Get Unlimited Access Now

Transcript from the "Composables" Lesson

[00:00:00]
>> So we've talked about composition API, we've talked about script setup. Now, we need to talk about something called composable. This is the new kit on the block when it comes to Vue, because it's basically a view specific terminology around a type of reusable JavaScript utility that uses the composition API.

[00:00:16] Hence, why it's called composable. And so for those coming from a React background, you might be familiar with the React Hooks, where they prefix everything with use, like use mouse position, that kind of thing. That pattern has also carried over into Vue. I'm gonna be demoing this shortly, but we'll be able to create some helper basic utility functions using the composition API.

[00:00:39] And then this is the elusive, how do we share some stuff between components without polluting and rewriting the same thing? Composables are your answer for that. Okay, so let's load up the counter real quick. So I'm gonna go inside of my App.vue, and this time, we're gonna practice this.

[00:00:55] I'm actually just gonna import my BaseCounter, and this is from base-counter here. We're gonna delete that, and then we're just gonna render out our BaseCounter just like that. Okay, so there you go. Also grip setup in the flesh right there. Okay, we have the ability to increment, that's fine.

[00:01:19] But what if we wanted the ability to count in other places? This is basically like an encapsulated functionality that we don't want to. So when we're looking at this functionality, again, this is a simplistic example, but for the sake of understanding composables, imagine if we wanted the count to be managed from multiple places.

[00:01:37] In other words, a base-counter, it's nice that it has it here. But what if we want the base, let's say, inside of user-card? What of user-card wanted the ability to also increment the count? At the moment, you'd have to duplicate that, it's kind of tricky. You would have to probably do some props to have your app manage that, but counted something that really we think about it.

[00:01:57] It really does belong in base-counter as a state, but it really doesn't make sense to put it at the app level, cuz it usually cares about a bunch of other things. So what do we have? We have composables. How does that work? Well, let's start by creating a folder called composables, just where you'll see a lot encode bases these days for Vue 3.

[00:02:18] And what we're gonna do is we're gonna create inside of that composables. I'm gonna create something called a count, I'll just call it a countStore, because that's what I wanted to do. I want to basically store what's going on with count. So I'll split this over with two columns so you can see what's going on.

[00:02:33] And so here, what we really wanna do is we want this piece of data. Let's start simple, let's make that shared so that we can show that in multiple places. The way you do that is we're gonna import a ref, rashy, no. We're gonna reverse engineer that a little bit easier.

[00:02:49] For those who are new to JavaScript modules, this might seem a little bit intimidating, but we're gonna basically build it up from scratch. When you have a JavaScript file that you wanna import into another file, the main thing you need to do is having to export, right? So normally, you would have an export like count of 10 like this, okay?

[00:03:06] Let's make it 100 like this. And then what we could do is you could then say, import countStore or actually import, we de-structure this part from composables/countStore. And we're taking out of that, we're taking the count out of this. And actually, let's make this new count so that visually, it's easier for y'all to see what's going on here.

[00:03:31] And then we can do here, it's inside of our setup method. We could say, yes, we're gonna go ahead and say return newCount. Okay, so to show you what just happened here, we just wrote a standard JavaScript, oop, what's going on? Did you fail to resolve import, composables, countStore?

[00:03:59]
>> You gotta backup-
>> Back up one level, yep, file name, that's it. Great Carl, and then to show that this works, we're gonna render this on the page, <h2>{{ newCount }}. You can see we successfully wrote a little piece of JavaScript that's now we're using two places.

[00:04:16] Now, again, to prove that this works again, let's continue proving this out. It's that we will then import the same newCount on user-card. Similarly, we'll use a setup method in here. I'm not gonna spend the time to convert everything right now just to kind of make the process a little bit easier.

[00:04:33] But we're gonna return a newCount here, and then we can actually then as an h2, also do newCount. So instead of the user-card, what we're gonna do now is also display newCount so we can actually prove that this was successfully imported to places. But we need this to actually render on the page.

[00:04:49] So we need to go to App.vue, and let's go ahead and bring in our UserCard. Although, I'm actually saying, yeah, UserCard is correct. There we go, perfect. So user-card here, but I believe UserCard had some props, though didn't require some props, it did. Object for name and food, that's fine, we can do that real quick.

[00:05:11] This will be a user with a name of Ben, and we just tick food. This time, we'll do Cheeseburger. Although, I did do that earlier, so for the sake of doing something new, we're just gonna do Ramen, save, boom. Okay, so you can see now, 100 appears here in the count, 100 appears here at the bottom.

[00:05:37] So we can verify that once more. We're going to countStore, changing this to 200. And you can see and refresh, you'll see that it's updating. But again, this is a constant, it's kind of weird. All right, so this is cool, but once again, we want the ability to be able to change that.

[00:05:56] So let's go inside of our base-counter. And this time, well, what might you do instinctively? We might go, well, instead of this, we'll say this.newCount. And when we click on it, we want newCount to also get incremented as well, and we'll increment it by 10. So we'll save that, we'll refresh, we'll hit it.

[00:06:17] And you notice, it's kind of working. This is kind of weird. But then you'll notice that it's working in this context, but it's not working in this context. And this is a little bit of a preview of the kind of UI bugs that we had to deal with over time.

[00:06:33] As developers, we're dealing with reactive state changes, and this is what a lot of the frameworks do well for us. So here's the deal, what we wanna do is what we wanna do. We wanna make this a reactive reference that Vue will contract. So what do we do?

[00:06:49] Import ref from vue, wrap this in a ref, save, refresh, everything's connected. And just like that, you have this little JavaScript file with just the one variable you care about shared across two different components at different levels, and everything's updating as you would expect. And so this pattern here that we're seeing regarding the combination of a setup with importing whatever you are dropping in is one that I would say is probably gonna be seen more in Options API.

[00:07:24] And that's why we spend so much time in composition API. In that, I would say going forward as architectures continue to evolve, composition API will become more and more popular in Vue apps. This is not to say that it is the one true right way, and that you have to write your apps this way.

[00:07:38] It's a very effective technique, and to try to ignore it for the sake of ignoring it doesn't really make a lot of sense. So for those of us who still love Options API, just sprinkle it in just like this. And then you get the benefits of composing together different pieces of functionality that you can reuse in your options, but then you can still get the benefits of options.

[00:07:56] For those of us who want to use composition API fully, then it really is just as simple as importing the thing and then using it.