Logic Extraction Overview0:00
Okay, let's take a look at logic extraction and reuse. You should definitely consider using this part of Decomposition API, even if you don't make use of its other features. This serves as an alternative to other Vue features that allow you to extract and reuse duplicate code. So things like mixins and scope slots. Let's take a look at a few examples. So the first example is taken straight from the docs, and it allows you to view your current mouse position as you move it around the screen. So we have X and Y coordinates, which are refs.
Implement Mouse Tracking0:26
mouse position as you move it around the screen. So we have X and Y coordinates, which are refs. We have a function that updates the X and Y coordinates. So it's getting it from the event, and the property name is pageX and pageY. We have a mounted hook that adds an event listener on the window and updates the coordinates on mouse move. And we have an unmounted hook, which just cleans up. So let's go ahead and start off by grabbing this and just putting it directly in our component. So I am going to go into our setup method here, and I'm just going to paste it up here. And we also have to import onUnmounted.
So I am going to go into our setup method here, and I'm just going to paste it up here. And we also have to import onUnmounted. So let's do that. And we also have to return X and Y down here. So let's do that. And let's also make a new section in our template that just shows that information. So right after itemsLeft, I'm just going to duplicate this, put a smaller margin here. And let's say X. And this will be the X coordinate. And let's make one for Y as well.
Create useMousePosition Hook2:09
we want to use it. So let's go ahead and do that. So I'm going to make a new folder here. And you can name it whatever you want. I'm just going to name it functions. And within here, I'm going to make a new file and call it useMousePosition.js. And it's good practice to prepend the name with use. And it's a JavaScript file. And what we want to do here is export a function with that functionality. So if you look at the docs here, that's what they're doing here.
And what we want to do here is export a function with that functionality. So if you look at the docs here, that's what they're doing here. They're exporting it and they're naming it useMousePosition. And let's just go ahead and grab this. So all of this logic that we had in here. So all of this and also what we want to return or what we want to make available to whoever uses this function. So let's paste that in first. And then let's return x and y because we want those values to be available to whoever uses this x and y.
And then let's return X and Y because we want those values to be available to whoever uses this X and Y. Okay. Let's save that. And now back to our component. So we no longer need this logic because that's extracted to our function. So what we want to do is first import it. So let's say import, say, useMousePosition from. So it's up one functions, useMousePosition. Okay.
So it's up one functions, use mousePosition. Okay. And now we can just use that function directly in here. So let's say useMousePosition and we can destructure the things that that function is returning. So in our case, X and Y and say equals useMousePosition. And with any luck, if I did this correctly, our component should still work. And it does. Cool. So now we can use this wherever we want or for any component that wants to use this same
Cool. So now we can use this wherever we want or for any component that wants to use this same logic. So I'm going to make another one here. Let's just say another of you, actually, let's just grab the template part that displays the X and Y coordinates just to show you that it does work. So in our script, then we want to export default and we want to import those functions as well or that function. So let's grab this import. Let's put it above here and we can do the same thing here if we want to use it.
So let's grab this import. Let's put it above here and we can do the same thing here if we want to use it. So use mousePosition right here, set up. And it's return X and Y. Actually, I'm going to rename X and Y. So when you destructure, you can rename it if you'd like. Let's say mouseX and mouseY. And say we are going to return mouseX and mouseY. And now these in the template are now mouseX and mouseY. OK.
Reactive vs Ref Gotcha5:48
OK. So did I do this correctly? And it looks like I did. But now our code is nicely tucked away into its own function and is easily reusable by just importing it wherever we need it. So there's one thing you should take note of if you're making use of reactive instead of refs. So let's go ahead and switch this over to use reactive instead. So I'm going to comment this out. Let's say const position equals reactive.
So I'm going to comment this out. Let's say const position equals reactive. And this will be X and Y. So X 0, Y 0. And let's make sure to import reactive here. And we no longer need that value because we're using reactive. So we have to switch this to position.X and position.Y. And we also have to change what we're returning. So now we're just returning the entire object itself. OK.
So if you look at the docs, you see a section here for ref versus reactive. And if you scroll down, this is the exact case that we're facing right now. So one way to fix it is wherever you're using it, you can return the actual object here and make use of the properties on that object directly. So that should bring the reactivity back. But I don't want to change the component that's making use of it. So to fix that, all we have to do is add this toRefs method if we're using reactive and that should fix everything. So instead of returning position directly in here, we can just do toRefs. And we have to import that up here at the end, toRefs.
Build Reusable Toggle Hook8:07
Let's take a look at one more example so you can better understand the entire workflow for this. So I'm going to bring back the ToDo component here. So let's see that. OK. So what I want to do here is add buttons that toggle the visibility of this item's left part and one to toggle the visibility of the mouse position. So let's add buttons to do that. So I'm going to go into toDo. And I am going to make buttons right underneath the title here.
So I'm going to go into todo. And I am going to make buttons right underneath the title here. So let's put a container for that. Say space-x-4. Let's put two buttons in here. Say px-2, py-2. Let's make it rounded. Let's make it bg-blue-500. And let's make it white.
Let's make it blue500. And let's make it white. And the first one is going to be toggleItemsLeft. And the second one is going to be toggleMousePosition. OK. Let's see how that looks. OK. So let's start with toggleItemsLeft and then we'll extract it to a composition function. So I'm going to put a method here or an event listener. And we'll call a method.
So I'm going to put a method here or an event listener. And we'll call a method. You can do it in line here, but we'll just call a method. Say toggleItemsLeft. And it's going to the setup method. And let's say or let's make a piece of state here. So const isItemsLeftVisible. Let's make it a ref and let's say true by default. Let's go ahead and make that function. So function toggleItemsLeft.
Let's go ahead and make that function. So function toggleItemsLeft. OK. And all this does is change the value of this piece of state that we just made. So isItemsLeftVisible.value equals the opposite of that. OK. And all we have to do is add a v-show or v-if on that section that we want to toggle. So that would be this. I'm just going to use v-show here. OK.
I'm just going to use v-show here. OK. And let's say isItemsLeftVisible. So does this work? And I've forgotten to return what we want to make available in the template. So let's go ahead and do that down here. Say isItemsLeftVisible and toggleItemsLeft. So let's try it again. And let's remove this. OK.
And let's remove this. OK. So that is toggleable. So we can do the same thing for toggleMousePosition. But this will require a new piece of state and a new method. So what we can do is extract this logic to a composition function and make use of that. So let's do that. So let's make a new file here called useToggle.js. I'm going to grab what we have here. And let's remove all this.
I'm going to grab what we have here. And let's remove all this. OK. And say use toggle. And I think I only need refs here. So let me remove this. And now all our logic in here can go in this new function. So specifically, we can grab this. And let me just comment that out. Let's put it in here.
And let me just comment that out. Let's put it in here. But now since we're extracting this logic into a generic function, it is a good idea to change these names to something more generic. So we can just say isVisible. And we can say toggleVisible. And same for these. So isVisible. OK. Now back to our toDo, let me just delete this.
OK. Now back to our to do, let me just delete this. And now we can import that. So let's say useToggle from useToggle. And we can do the same thing that we did here. So we can just make use of that useToggle function and destructure what we want out of it. And if we want, we can rename that. So I'm actually going to rename it. And hopefully my VS Code can detect this.
So I'm actually going to rename it. And hopefully my VS Code can detect this. So let's see. And doesn't seem to work, but that's OK. Because this one was working earlier. So isVisible But now in the context of this component, we want to rename it to isItemsLeftVisible. And for the other one, it's toggleVisible in the function that we're importing. But we want to rename it to toggleItemsLeftVisible. And we're already returning it down here because we had the logic in here earlier.
But we want to rename it to toggleItemsLeftVisible. And we're already returning it down here because we had the logic in here earlier. So let's see if this still works. And it looks like I, again, forgot to return what I want to make available. So like I said earlier, or in the last video, this is going to be the number one thing that you keep forgetting when you're making use of the composition API. So whenever I make use of isVisible, that's why my VSCode autocomplete did not work. toggleVisible. And let's see if this works. toggleItemsLeft.
And it does. Cool. Okay. So now if I want to use this same logic for the other button that toggles this part, we can do that. So for this, let's say @click equals toggleMouse, or no, mousePosition, mouse is fine. And let's put a v-show on this, say, isMouseVisible. And now we can just duplicate this, we can say isMouseVisible for this. And we can say toggleMouseVisible for this. And we have to return that down here.
So now we can toggle this, we can toggle this, and we are making use of this using the composition API and composition functions. So I hope those examples gave you a better understanding of the composition API and how to extract and reuse your duplicate code.
