Vue JS 3: Composition API for State Management (Vuex Killer?)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] in this video i'm going to show you how to set up state management for your vue.js3 app by using the composition api instead of using view x i'll also give you three pros and three cons for using this technique instead of ux if you're new here my name's danny i'm an indie app developer and creator of budget if you want to learn about vue.js web development cross-platform apps and all that good stuff click subscribe and click the bell so you don't miss anything every subscription helps me to create more content for this channel so what we're going to do here is set up this basic counter app using the composition api at the component level by setting up some reactive data and methods then we're going to move all of our data and methods into a custom state management store which we're going to create using the composition api instead of using view x and we'll also be adding some ux style state methods and getters to our store as well and this is basically the same app i created in my learn view x in 30 minutes video which you might want to check out let's get started by creating a new view 3 project using the view cli so i'm just going to google view cli and jump to the website get started installation and if you don't have node installed then you need to install that which you can get at nodejs.org probably want to install the one on the left and you can then install the view cli in your terminal by using this command and once that's installed you should be able to create a new view project with the view create command so i'm going to jump to my terminal which is just running within vs code which is the editor i'm using and you want to make sure you're in the folder where you store your projects and then just run view create and let's call it composition api state management i'll fire that we want to choose manually select features and we want to enable the router with the space bar and disable the linter and then just hit enter and we want to choose view three choose no to history mode dedicated config files save this as a preset i'm going to choose no okay it's finished creating our project so we just need to run npm run serve in that folder and i can see the folder here and i can see i've called it management instead of management so i'm just going to rename that and then drag this folder into my editor open up the terminal and just run npm run serve and that's now running so we can just command and click on this link and see the basic vue.js app running in the browser let's get started by creating a basic counter app on this home page so i'm going to jump to source and views and home.view i'm going to get rid of this hello world component which is adding all of this text down here i'll get rid of this import i'll get rid of this component subject as well and i'll save that and we can actually delete that hello world component in the components folder so i'll delete that okay so let's add a counter to this page so after this view logo image we're gonna add a div with a class of counter and i'll just put zero in there for now and let's add some buttons for decreasing and increasing the counter so a lot of deal with the class of buttons and then inside there i'm going to add a couple of buttons one which has a minus symbol inside it and one which has a plus symbol and i'll save that and let's add a little bit of style to make these things a little bit bigger so first i'll style the div element just to put a bit of space between each of the divs so i'll just add a margin bottom set that to 10 pixels and let's make our counter a little bit bigger so we'll target the counter div with this counter class and i'll set the font size to 80 pixels and let's make these buttons a little bit bigger so i'll target the button element inside that div with a class of buttons i'll set the font size to 40 pixels i'll set the width to 100 pixels and we'll add a bit of horizontal margin as well so i'll set the margin to zero on the y-axis and 10 pixels on the x-axis okay this is looking decent enough now so let's make this actually work by setting up some reactive data and some methods i'm going to be using the composition api for this and if you need to learn the basics of the composition api then check out my composition api versus options api video so we're going to need a setup method so i'll add that to our export here i'm going to set up a ref for our counter so we need to import the ref method from view um we'll set up a ref for our counter so we'll call this counter and set that equal to the ref method and pass in our initial value for that ref so we'll just set it to zero and to make this available to our template we need to return it so i'll add a return object and just pass in counter and i'll save that we can now replace this hard coded zero with our ref so i'll add double curly braces and then counter and save that just reload it and we can still see zero here so if i change this value to two then we see it update so that's all hooked up set that back to zero so let's trigger some methods when these buttons are clicked so i'm going to add some click handlers to these buttons i'll just select them both here and add a click handler and on the plus button we want to trigger a method called let's say increase counter and then on the minus button we'll trigger a method called decrease counter so i'll just change it there so now we need to set up these methods so we'll make these constants so const increase counter set that equal to a function and for now i'll just log out increase counter then i'll just duplicate this and set up our decrease counter function and change the log as well now because we're using these methods in our template we need to return them here so we just need to return decrease counter and increase counter so we'll save that and let's just see if these functions are being triggered and yeah we can see decrease counter and increase counter in the console so what do we want to do in these methods well in this increased counter method we just want to increase the value of this counter ref by one however when we create a ref like this and assign it to a variable it actually creates an object and within that object is a property called value and that's where our value is for that ref so in this increase counter function we just want to do counter dot value to get access to the actual value and then plus plus to increase it by one so i'll just copy this and paste it into the decrease counter function and change that to minus minus and let's save that and see if it's working yeah the plus button is working and the minus button is working as well okay so our app is basically working let's create a state management store for all of our data and methods using the composition api instead of using vue x so that we can access all of our data and methods from anywhere within our app and not just on this home page so i'm going to create a new folder within the source folder called store and inside that i'm going to create a file called index.js and this is where we're going to create our store so we're going to need somewhere to store our data or our state so let's create an object called state where we can place our counter property so i'll add a counter property here and set it to zero and we need to export this object so i'll add an export default and pass in this state object and we need this state object to be reactive so that if any of the properties in this state object change then any of the components in our app which are using properties from that state object will be updated straight away and we can do this by making this state object a reactive object using the composition api's new reactive method and if you want to learn more about reactive objects check out my composition api video and all we need to do is import the reactive method from view so import reactive from view and then we just want to fire this reactive method on this object so we can just add reactive and then surround this object in parentheses and save that and this object is now reactive so we've created our store and we've added our state object and made it reactive and we want this store to be available everywhere within our app and one way we could do this is by importing our store into our root view component up dot view and then using the provide method to make the store available to all of app.view's child components since all of the other components of our app will be children of app.view so i'm just going to add a script section to app.view and we want to import our store from this index.js file in the store folder so we can just do import store from then which is an alias to our source folder and then slash and then store and now we want to use the provide method to make this store available to all of the child components of app.view and using the options api we could do it like this by just adding a provide object and then passing in this store variable however since we're doing everything with the composition api let's do this the composition api way so we're going to need to import the provide method from view to do this so we want to import provide from view and then we can just get rid of this provide object and add our setup method then we can just fire the provide method and then pass in a name for the variable that we're going to provide as a string and we're just going to call this store and then for the second parameter we just pass in the value that we're going to assign to this variable which again is this store that we're importing here so i'll save that and we can now inject this store into any of the child components in our app so let's inject it into our home page first so i'm going to jump back to home.view and to inject this we're going to need the inject method from view so i'll just pass that in here inject and then in our setup method we can set up a constant for our store and we'll call it store and we'll set that equal to the inject method and pass in store as a string and we also need to return this store constant in our return statement here so i'll just add that here and save that and we should now have access to our store within our home page using this store constant so first of all let's replace this counter which is currently using this local counter variable here with the counter property which is in our state in our store so this property is going to be at store dot state dot counter so i'll jump back to home dot view and jump up to our counter here and let's replace this counter with store.state.counter save that i'll just reload the page and we can still see a zero on the page here so if i jump back to index.js change the value of this counter to 4 then we see it update so we're now successfully using the counter from our store instead of the counter that's on the home page so i'll set this back to 0 save that jump back to home.view and we don't need this local counter variable anymore so let's get rid of that and also get rid of it from this return statement as well and save that okay let's move our methods into our store now so i'm going to jump back to the store file and we could if we wanted to set up an object for mutations and an object for actions if we wanted to keep this really similar to vue x but i want to demonstrate that when we use the composition api to set up state management we can do things quite differently from vue x and we can set things up however we want to so instead of having mutations and actions i'm just going to have an object called methods and place all of our methods inside that object so i'll set up a new constant called methods set that equal to an object and we need to add this methods object to our export here so i'll add that here and we can now place all of our methods inside this object so we need a method for increasing the counter so let's create a method called increase counter and i'll just duplicate that add a comma here and change this one to decrease counter and all we want to do in these methods is either increase this counter in our state by one or decrease it by one so in this increase counter method we can just do state.counter plus plus and then in the decrease counter method we can just do state dot counter minus minus and i'll save that and we should hopefully be able to trigger these methods from anywhere within our app where we're injecting our store so let's trigger these methods that are in our store when the user clicks on these buttons so i'll jump to these buttons on these click handlers and instead of triggering these local methods let's trigger the methods that are in our store so these are going to be at store dot methods and then dot increase counter or dot decrease counter so i'll jump back to home dot view and on our plus button we want to trigger store dot methods dot increase counter and then the same for the decrease counter so we just want to do store.methods.decreasecounter we can now get rid of these local functions that we're not using anymore so i'll get rid of both of these and get rid of them from this return statement as well and save that and let's see if this is working yeah it seems to be working we can increase and decrease the counter so now that all of our data and methods are in this global store we should now be able to use any of our state properties or any of our methods anywhere within our app so just to demonstrate that let's just stick a counter on the about page so i'm going to open up the about page source views about dot view and again we need to inject our store into this component like we did on the home page so let's add our script section and our export add our setup method and we need to import the inject method from view and then in our setup method we need to set up a constant for our store set that equal to the inject method and pass in store as a string and then we need to return this store constant so we'll add a return object and pass in the store i'll save that and i'll change the text in this h1 to counterworks everywhere and then i'll add a h2 and we'll just spit out our counter so again store.state.counter and i'll save that and we can see our counter there so if we jump to the home page and increase this counter jump back to the about page we can see that it's been updated if you found this video useful so far smash the like button and leave a comment telling me whether you prefer using vuex for state management or using the composition api so when we use view x for state management as well as state mutations and actions we also have getters which can get some data from our state change it or filter it in some way and then make that available everywhere within our app so let's add a getter to our custom store so let's say we want to spit out the square of our counter so the counter multiplied by itself well we could create a getter to do that for us but first i'm just going to add some markup first for displaying the counter squared so i'm going to jump to home.view and then after this counterdiv i'll add another div with a class of counter squared and inside that i'll first of all spit out the counter saw.state.counter then a lot of space and a new line and superscript tag with two in it which should look like a squared symbol then a lot of space and an equals then a space and a new line for now i'll just put xxx but we'll replace this with the value from our getter later on so i'll save this and that looks pretty decent so let's create a getter which will grab the square of our current counter so i'll jump back to index.js and i'm going to create a new object here called getters so const getters equals objects and we need to export this so we'll add that here as well let's create a method in here called counter squared and we just want to return something here and we want to return the counter multiplied by itself so we can just return state.counter multiplied by state.counter and i'll save that and hopefully this getter should be available on our homepage so jump back to home.view and i'll replace this xxx with double curly braces and our getter is going to be at store dot getters dot counter squared so we can just put store dot getters dot counter squared and in view x we didn't need to put parentheses after this function name because v x automatically resolved it to a function but with this custom solution we are going to have to add the parentheses like that so i'll save that and it seems to be working 5 squared is 25. 6 squared is 36. let's set up some two-way data binding with our store so let's create an input where the user can enter a color name or a color code which will then change the color of our counter so first let's add a new state property in our store so i'll jump to index.js and add a new property to our state called color code and we'll just set this to blue i'll save that and now let's bind to the style attribute on our counter and set the color to whatever's in this color code property so i'll jump to home.view and i'm going to split the attributes on this counter div using the split html attributes extension and we'll bind to the style attribute i'm going to pass in an object and we want to change the color css property and we want to set it to whatever's in this color code property so we want to set it to store.state.colourcode so i'll just set this to store.state.color code save that and we can now see our counter is blue because we have it set to blue here if we change this to red then it changes to red so let's add an input to our home page and bind it to this color code property so the user can change the color so i'll jump to home dot view then after our buttons div i'll add another div and i'll put an input in there and i'll split the attributes um i'll add a placeholder which just says enter color code save that and we can see that on the page so how can we bind this input to this color code property in our state well one potential advantage here over using view x is that we can just use the model to directly bind this input to this state property so we don't need to set up a computed property and bind it to this input and then add a get method and a set method to that computer property like we need to do with view x because with view x we're only allowed to mutate the state by using a mutation but with this custom solution we don't necessarily need to do that so i'll jump back to home.view onto this input and we can just go ahead and add a v model to this and set it to this state property so store.state.color code so store.state dot color code we'll save that and i'll reload so if we change this field now to blue then it's updating the color code property in our state and we see the color of the counter change so you might see this as an advantage being able to two-way bind with our state properties without too much hassle however you may want to protect your state from outside mutations so that we can only actually change state properties using methods that are in this store just like view x does and we can do that if we want to we can do this by using vue.js's read-only method so that when we export our state here we only export a read-only copy of our state so that any attempt to change the state from outside of this store file will fail and return an error so to do this we need to import the read only method from view so we can just add that here read only and then down in our export when we add state here what it's basically doing is creating an object property called state and then setting it to state this state object here so what we can do to export a read-only copy of this state is just simply fire the read-only method on this state object here so we can just surround this in read-only and parentheses and we should now no longer be able to change the state or mutate the state from outside of this store so i'll save that and i'll reload and if we now try to change this input we can see the color of the counter doesn't change and we see some warnings in our console set operation on key color code failed target is read only so now our store is completely protected from outside mutations just like the state in view x is but now that it is protected if we want to make a change to this color code property then we're going to need to bind this input to a computed property with a get method and a set method a get method for just grabbing the initial value from our state and then a set method which will be triggered whenever this field changes which then passes the new value in the input to a method that's in our store which then updates the color code data property so i'm going to jump back to home.view and this input and instead of binding it directly to our state property let's set up a computer property called color code and we'll create that in our setup method and so we're going to need the computed method from view to do this so i'll pass that in here and i've just realized we're not using the ref method anymore so we can get rid of that as well so let's set up this computed property color code so to do this we can just fire the computed method pass in an object and we want to assign this to a constant or a variable and we want to assign it to a constant called color code so we'll just add const color code equals and we need to return this computed property so i'll pass it into our return statement as well color code and let's add a get method on a set method to this computed property so get another comma and then set so inside the get method we just want to return the value that's in this state property so we just want to return store.state.colorcode so i'll just do that return store.state.colorcode and i'll save that and refresh and that seems to be working because this input is populated with red which is the initial value of this property so i'll jump back to home.view and this set method will be fired every time this input changes and it will return the latest value of that input so we just need to pass in a variable name here i'll just call it val but you can call it whatever you want and i'll just log out val make sure that's working so if we start typing into this input then we can always see the latest value of the import being logged out so now we just want to send this latest value to a method that's in our store in our methods object which will then update our colour code property with the latest value so we'll jump back to home.view and so when this set method is fired every time the input is changed we just want to trigger a method that's in our store which we've not created yet so let's trigger a method called set color code so we just want to do store dot methods dot set color code and then we want to pass in the latest value like this so i'll save that and now we need to create this method set color code so i'll jump back to index.js add this set color code method which is going to be expecting a value and all we want to do in here is set this color code property to this value so we can just do state dot color code equals val so i'll save that and hopefully this is working now i'll reload change the value of this input and yeah the counter changes to blue so that all seems to be working now okay so this is basically how we can set up state management using the composition api instead of using view x but before you start creating projects in this way it's important to understand the pros and cons of using this technique instead of view x so i have three pros and three cons and pro number one is that we can structure this store however we want to we can give all of these objects any names we want we don't need to use state methods and getters and we don't even need to place our methods inside a object like this if we don't want to we can just declare our functions at the root level and export them down here if we want to and we could add all sorts of different objects for different purposes so you might have one object for one kind of method and then one object for a different kind of method so we really have almost infinite flexibility with how we set up our store if we use this technique uh pro number two is that we're not forced into using mutations and actions so with a larger view x app we often end up with tons of mutations and actions which all have the same names and many of those actions are just simply passing a payload onto the mutation which can make your store feel quite bloated with a lot of kind of unnecessary code but with this technique we're not forced into doing that although we still have the option to break our store up into mutations and actions if we prefer to pro number three is that we can two-way bind with properties that are in our state if we're using this technique which could be quite handy and could mean that we avoid having to set up lots of different computed properties and binding our inputs to those computed properties however if we do want to protect our state from outside mutations like ux does then we still have the option to do that by using the read-only method okay so now for the cons so con number one is that we don't have all of the excellent debugging capabilities that we have with view x so when we use view x we can use the view dev tools to see everything that's going on within our state and we can even change our state properties from view dev tools we can see exactly which mutations are being fired and exactly which components triggered those mutations and we can even step back in time through all of our mutations and with our composition api store we don't have any of these capabilities and con number two is that we don't have access to view x plugins such as the vuex persisted state plugin which makes it really easy for us to persist the user's state in the user's browser in local storage although we could recreate that functionality with a little bit of extra work and con number three is that we need to inject our store into every component which uses it which does add a little bit of extra code whereas with ux we don't need to inject our store or import it or anything we always have immediate access to everything that's in our store by default so that's all of my pros and cons if you can think of any more then please leave a comment down below make sure you check out my learn ux in 30 minutes video check out my video on the basics of the composition api as well please click my face over there and subscribe every subscription helps me to create more content for this channel thanks for watching and i'll see you in the next one
Info
Channel: Make Apps with Danny
Views: 28,172
Rating: undefined out of 5
Keywords: composition api tutorial, composition api, compositionapi, computed, free course, intro to composition api, intro to vue 3, intro to vue, javascript, learn vue 3, learn vue, programming, reactive, ref, tech, vue 3 composition api, vue 3 course, vue 3 tutorial, vue 3, vue composition api tutorial, vue composition api, vue js 3.0 tutorial, vue.js 3 tutorial, vue.js 3, vue.js, vue, vue3, vuejs 3, vuejs, vuejs3, vuex, vuex tutorial, vuex state, state management
Id: _k4GM5cmm68
Channel Id: undefined
Length: 30min 4sec (1804 seconds)
Published: Wed Jan 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.