Vue.js: State Management, Component Hierarchy, Props and Vuex

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello friends welcome to coding garden with CJ in tonight's episode we are going to give an overview of state management component hierarchy and props with view Jas now in some of my past videos on VJ s they have been very introductory we've kind of just built one component with lots of functionality inside of it but what I want to show tonight is essentially how to break things up and structure your app in a more scalable way typically you'd structure app in this way if you're working on a larger team or working on a larger app so the main idea when structuring your app this way is that all state will live at the top level and essentially we're gonna build an app that lists out rockets and then allows us to add new rockets so I think like Saturn v5 the bfr from SpaceX different rockets like that we're just using it as an example but the Amane idea is that all of the state is going to live at the top level component and then all of that data is going to be passed down as props to child components and child components will then call functions in the parent component to do things like delete a rocket from the list or to add a new rocket to the list and I have a super basic API that I set up that just returns an array of rockets so there's the Falcon Heavy Energy here from Russia sls block 1b and the bf are from SpaceX and so essentially we're gonna build an app that lists out these Rockets allows us to add a new rocket just locally we're not gonna be making any API requests to add rockets and then remove a specific rocket the main idea is we're gonna have an app that looks like this so we'll have like this top level component called rockets and then inside of it it will have child components one of them being a form where we can add a rocket and we're essentially gonna pass a function down to that component called add rocket which will then call to pass it back up and as I mentioned all of the state is gonna live on this component so this component is gonna be the one with the array and then I'm also gonna have a rocket list component and there we were going to pass down that entire array of rockets from the parent level component to that component we're also going to pass down the remove rocket function and then inside of there we'll have yet another component just called rocket and this will be the actual rocket itself and it'll get passed down its rocket data and then also get passed down that and remove rocket functions so that it can remove itself from the array in the parent component if you're totally new to stuff like this a lot of this it might sound like nonsense but as we move along it should start to make sense if you are watching live be sure to throw a message in the chat ask a question say hello I'm here for you and so we're gonna build this it'll be fun but if we have enough time I would like to convert the thing to use view X so a lot of time when we talk about state management it's all about kind of like top-down control and we can do that with the built in state in view but another way to do that is with a library called view X and then again if we do have time I would like to refactor maybe not the beautify app maybe like the player score counter or the to-do app or the reddit clone I built all of these things in the view apps traffic Anza and so we could potentially refactor each one of those things to use this style of coding where essentially we're passing things down and have all the state at the top rather than doing everything inside of one big component hello Andy hello Brooks welcome to the stream thanks for watching ok so I think I'm gonna get started and essentially we're gonna build a nice little view app so got a folder here I'm actually gonna use the latest view CLI if you have not used it it's pretty sweet you can do a view create and then you give it a name we're just gonna call this rockets app and it will ask you a series of questions so when you if you've used the CLI tool before you can actually save presets but I'm just gonna do manually select features and this is my break timer we are just getting started but let's take a quick break welcome James to the screen hmm was that true welcome to tonight I am drinking passionfruit Lacroix but the new view CLI is sweet it's totally plug-in based so instead of being based on an initial template that gets downloaded to your machine you get to pick and choose the different plugins you want to use so I I won't use the router because we're just gonna have one route but it's gonna have lots of components inside of it don't really need any pre-processors I will use linting and formatting well that's it and I'll use yes lint air B&B none of those options and instead of dedicated config files I'm just gonna put everything in the package.json it'll look a little bit more cleaner by doing it that way here's the other thing so after you've selected all of your options you can save a preset so in the future if you want to build an app that uses linter and Airbnb and all of your configs in the package.json you can just instantly select that and not have to answer all the questions again so I'll save this I'll call this lint and package cool and so that gave it a name and then the next time I want to build an app with the same plugins I can just do that actually they might be at a new beta I haven't updated in a couple of days the other cool thing is now that they have this plug-in infrastructure there are lots of new plugins being developed like there's a plugin for beautify where you can just run one command and it will automatically add beautify to your app there's a plug-in for Apollo view which is a graph QL client all kinds of plugins which essentially just allow you to easily integrate some library with a view CLI generated app and something's happening so this is creating this Rockets app directory and installing all of the dependencies and it structures the folder in a slightly different way so I'll kind of review that before we get too far into it and if you're familiar with the old CLI tool the command was NPM run dev now it's MPM run serve so I'm gonna go into that folder and then do NPM run serve cool and your basic view app which you might be accustomed to but there's it looks a little bit different there's some different links and stuff in there if we look at the folder structure you'll notice it's it's very bare and the main thing with the new CLI tool is that all of the base web pack config and everything like that is stored inside of an NPM module and if you want to modify it you can just add your custom config to this file here like if you want to add new plugins to web pack you add that here and it gets merged in with the base config which is pretty sweet because out of the box we have like a really simple file structure but under the hood it's using webpack with all that same configure that used to be in the folder before cool and so the kind of the main layout is public this is where you're really where your static files can go this is where your index of HTML is and then your main j/s looks pretty much the same your app dot view looks pretty much the same it's just bringing in like a custom component oh I I didn't use router I was gonna say because if you use router it actually creates a folder called views and all of your top-level routes which are defined like used in your router file are in that folder and then any sub components are in the components folder today we're pretty much just gonna put everything in the components folder maybe I'll make one one view and put it in the views folder cool so let's get started so let's do just that so like in the root of the source directory let's create views and inside of there I'm gonna create rockets top view and this is our top level component where all of the state is gonna live and everything like that we'll just do a basic little template each one rockets save that and then we'll bring that into the app table view so instead of bringing in hello world we're gonna bring in rockets from views I believe we still have access to the @ sign rockets and here's what we used to write in app dot view I'm just gonna bring in the rockets component just like that so that's there let's go ahead and remove all of the default styles I think I'll use like boots watch today or something like that and for now just get rid of that hello world component let's see what we got there we go it worked and hard refresh cool so we're now if we look back at our readme we're kind of at this level here so we have our app and then at the top level is this top level component and the app itself is dumb there is no state stored at the top level app all of that state is going to be inside of the Rockets component so if you look in rockets let's go ahead and start getting coated in there coding in there first thing we want to do if we look back at our readme is we need a form for adding a new rocket so we're gonna create that component so inside of the components folder create a new file let's call this new rocket form view give it a template I'm just gonna go ahead and a basic little form here we'll have a label for rocket I think rocket name and then an input type is text name is name and ID is name so there's our form let's now bring it in to rockets top view so I'm gonna import it in at the top import new rocket form from at slash components slash new rocket to form and then inside of the options for this component we're gonna say components and inside of there we're gonna throw the new rocket form so now we have access to it so here I'm just gonna add a section and then at the top I'm gonna bring in this new rocket form like that what do we get we get the form at the top suite and you might have actually seen me in previous videos like if I brought in a component that's camel cased I used it as camel case in the template technically that works but it's not good practice so if you define something as having camel case you actually want to use - case when you're using it in the template let me plug in my laptop real quick okay and I'm gonna bring in bootstraps so just so we can get a little bit of basic styling I'll bring boots watch let's use it's used darkly so I'm just gonna grab the minified CSS and then I can bring this into index.html it's right there throw a link though with that CSS and then we get some basic styling let's go ahead and add the form styles to it I think when I had a nav bar up at the top - let's do this blueish one oh that's weird and just while we're at it let's put it in another component so like in our app top view will have the nav bar component up at the top and then the Rockets component right below that so let's create a simple little component let's call it a nav bar top view and then this is just it's really it's just gonna have a template it doesn't need any script or CSS we'll throw that in there won't be any links and here we'll say Rockets and now we'll bring that into our app top view so let's also import the navbar from at slash components slash nav bar and then we'll bring that into our component or right and now we can use it so if I have you need one top level component will put the rockets inside of there and then right above that I will put the nap are like so what do we get we get a nav bar let's go ahead and find those CSS classes for the form so I'm using bootstrap for if you look at components input group well let's get forms how we do this okay so we have a class form group so form and then we have a div class form group and then that has the label inside of it and then that has the input inside of it but it has a class of form control like that there we go I guess the other thing I'll do is inside of here one side of app top view I want this to have a container class just so it pushes it in a little bit cool so a rocket has a name a description a country and an image so we're gonna need all of those in our components here so we've got a name this is formatted a little weird whoa I don't like any of that okay let's drag in go in and then these go in one okay so we need a similar form group for the description this is gonna be for description and then a name and the ID is gonna be description but we'll actually make this a text area so the description can be a little bit longer like that cool name description country just be let's put that below the name so we've got name country description and lastly we need image and so that again is just gonna be a nice little input box image image cool I guess the other thing is let's let's hide and show this form so it's not showing all the time we can have like a simple little button that just hides and shows it so I guess to do that we're gonna put the form inside of a section because we can only have one top level component will throw the form in there but we will add a button that says show form and this form will only be V if show form and when we click this thing it will be show form equals not show form so a question from Brooks in the chat is there a company or organization behind view officially no it's a totally open source project that was created by Evan you who used to work at Google and now he works on the project totally open source it is however supported by a lot of different companies like if you look supported and turned like monetarily like if you look at UJS website you can see there's some sponsors on the website and they essentially contribute to Evans patreon and yes oh well patreon sponsors here and there are essentially just contributors but there is no company like deciding what's gonna happen next with you it's all totally community based and all of it happens in there discord there's actually a vule and discord where they have in-depth talks about what should happen with the library there's also the github repos and issues but it is a very very open source library cool what were we doing yeah so we got a button so essentially we need this show form to exist on the data for this form so data is a function that returns an object and we're gonna have show form and initially that is false so when the page loads that's there but if we click it it shows it if we click it again it goes away click it click it let's change the button to not be the same color let's do danger button danger and the other thing is let's push down the rockets component a little bit we can do a bootstrap thing is margin-top some M value and it'll push it down a little bit cool so now if we show the form that's there and it hides the form cool so what we want is essentially a button that will then add the form so at the bottom of the form let's add ourselves a button will do button success we'll say add rocket and when we click this button we want to add the rocket where do we want to add the rocket so if we look at the hierarchy rockets exists here and then new rocket form exists there but I want the Rockets array or all the Rockets to exist inside of this component here so that's that's where I'm gonna add them so the right now we're in the Rockets component and let's just give it a name so we're clear on where we are so data is gonna be a function that returns an object Amy asked how does my and it's doing a lot better like it does not get as sore when I type for a while like it was like the first few weeks it does it comes off this coming Monday so it's it's healing definitely healing thanks for asking and then I want this component to have an array of rockets initially it's nothing and then when this component gets mounted I want to make the API request that is going to get this array of rockets now because we're being all modular and such I'm actually not going to make the API request right here I'm going to create it in a separate file and then make the API request so let's do it so in my source directory I'm going to create a Lib folder inside of there I'm gonna create a file called API Jas we're just gonna export an object that has some methods on it like get rockets and this is actually going to do the fetch so I'll return fetch with some API URL and then take that result and turn it into a JSON but what is our API URL let's define it I have it right there cool so this file exports an object that has a function on it called get rockets I'm now going to import this file into my talk level component and that's where I'll actually call this this method and actually while we're at it let's use async/await let's do this so we're going to say res is a weight and we're going to return res de so cool all right now in our component let's see how this gets used so first we'll bring in the API so I'm gonna say import API from at /lib slash api and then when the component is mounted I'm gonna say API dot get rockets and we can await that so we can say Rockets equals oh wait get Rockets and let's just lock it let's make sure it works and because I'm using a weight I need to mark this as an async method ok let's see what happens hey we get our rockets so that's an array of rockets and actually while I'm here I'm just gonna go ahead and push up the code because I've written quite a bit of stuff you can take a look at it at home I already have a git repo this oh okay yeah when you use the the the new of you create command it actually creates a git repo inside of the folder I don't want that cuz I want mine might get repo to be one level above that yeah initial rocket app go and I'll push it up if you look below in the video description there is a link to this repo I now have a coding Guardian organisation and the repo that I'm working on right now is there so we can see oh man that wasn't supposed to happen it added it as an embedded repo oh alright here's what I'm gonna do I'm gonna blow it away gone and I can do this because there was nothing git remote add origin that get push origin force it delete all the stuff origin master okay the code is there now so you can pull this down check it out while I'm coding on it let's keep going though so essentially we have our top level component called rockets when it loads it calls the API to get the rockets and then we actually want to set that on data and for now let's just show it right here we'll throw the rockets in there make sure that we're getting it so actually I could just say this Rockets equals a way to API get rockets and we get all of the JSON data there cool so before I get coding in the like essentially we have to pass a function down to this form so that it can then add it into this array let's go ahead and code up the rocket list so we can pass this array down because that's going to be a little bit easier to just display the data rather than passing functions around so essentially I need a new component we're gonna call it rocket lists dot view and this won't have any custom stylings it will have a prop called rockets and that's gonna be an array that we're gonna pass down and essentially for every rocket in that Rockets array we want to show a rocket component so I want to be able to do I'm gonna code a bunch of stuff that doesn't exist and then I'm gonna make it all work I want to be able to say okay I want a rocket component but for every rocket in Rockets past that rocket down to the rocket components okay so this is the rocket list let's create another component called rocket view and I promise I will go back and walk through everything we just did because I'm feel like I'm moving pretty fast and this component is gonna have a prop that's just rocket because we're gonna pass down a single rocket and for now let's just throw an h2 in there with something like rocket dot name okay so we actually need to bring this rocket component into the rocket list component so it has access to it import it from at slash components slash rocket and then we define it on the components here rocket so this is the rocket list it brings in the rocket component and then for every rocket in the array we create our own rocket component and pass that rocket down again I'm going to kind of review what this syntax means and what's happening but then inside of here we should get access to that rocket and list out its name and then in here we actually want to bring in the rocket list so right here I want to be able to say rocket - list and I'll need to bring in the rocket list components slash rocket list and then also let this Rockets component know about the rocket list component and now we want to pass those Rockets down to this rocket list so we're gonna say Rockets is bound to the Rockets of this component what do we get broken rocket list was not found let's take a quick break Harbor fresh unknown custom element rocket list did you register the component correctly rocket - list maybe not cannot use oh that's that's the issue cannot use before on a stateful component room because check this out so I've mentioned it several times we cannot have multiple elements as the root and even though this looks like one element we're actually repeating it so that would actually give us like five root elements so I really just need to throw this in like a section and then repeat the rocket inside of there that cool so it's working we'll review in a second what happened here okay so let's actually go back to our readme and kind of because I think we've we've essentially reached the component hierarchy now we're gonna start passing around methods so we can pass data around and make it work but ultimately top level I have this rockets component inside of that it brings in the new rocket form and the rocket list the rocket list gets its array of rockets from the Rockets component so this syntax here means Rockets is a prop on this component and we're binding it to the Rockets of this component so if we look at the actual code this component here has rockets on its data right so when we say : rockets equals rockets we're essentially saying the prop called rockets on this component is rockets from data and we're passing that down so when the component first loads and let's actually just comment out our API request so when the component first loads we're just passing down an empty array and nothing should render but the moment it's mounted in the moment this API request finishes that rocket array is overwritten and that gets passed down and if we look inside the rocket list now that Rockets actually has values in it we repeat over it and create a new rocket component for each one inside of that array so rocket list gets its rockets from data inside of that component it iterates over that list or that array to create a new component and then we're passing down data even further so this is an array and then this is each thing inside of that array so we're essentially saying take one of the Rockets and pass it down to this new rocket component set its rocket prop to be the value of the rocket and we're binding it there so if we look inside of rocket dot view it has a single rocket prop and now inside of here we have access to all the props of each individual rocket so rocket dot name rocket description rocket dot image etc and so you'll notice we define our prop there so it knows that whenever we state : rocket we're saying that prop value should be equal to that and then also here we're defining the prop on the rocket list to be rockets and that exactly corresponds to the prop name there well when I lean forward my green-screen got weird okay think about that for a second come up with maybe some questions I realize I'm going kind of fast and this is a lot of components and a lot of stuff happening any questions you have no dumb questions I will literally answer anything what I'm gonna do right now is make this look prettier so I'm gonna go to the bootstrap Docs and find like a image card or something like that yeah yes we just just could use that so we have our rocket list let's do this so the section has a class of row and then the rocket itself instead of being an h2 is gonna be a div with a class of card and we're gonna do column - three calm - four so there should be three rockets across and then the source of the image is going to be a rocket image and we will bind that the alt tag the alt text will be rocket dot name and we're also binding that the title is going to be rocket dot name the description is going to be rocket dot description and then for now we'll just hide that button what do we get cool so each rocket takes up four columns it's a twelve column grid and we've got the falcon heavy with its information we've got an ER here we've got that thingy cool let's just add some custom styling though so actually I'm gonna add a style style tag here let's create a class for like rocket image and let's say the max height is like 400 pixels and then the width is auto yeah some like that and then we'll just add this class to this image hard refresh that didn't work hmm so I want the width to be auto what if I said that as important No why is that weird squished Otto typically maintains aspect ratio and let's look at it yeah what if we just hard code the height so let's say height is 400 pixels and then that's odd why oh is it flex boxed yeah that's why what if we did this well if we dared of that or if we put a div there and then put this image inside that div yeah well do it we just need to Center it though and so we can say margin is zero CSS is not my strong suit anyone want to tell me how to Center this image I also probably just won't worry about it anybody cool not gonna worry about centering the image but we have some cards there so now we're on to the good stuff now this form here we want to be able to say let's actually is MIT no a rocket that I can add SpaceX rockets there's the Falcon Heavy I know that it's already in the list though achievements Falcon Heavy Falcon not it's that the Falcon 9 let's find it on Wikipedia I'm gonna find a picture Falcon 9 wiki no jeez there it is the Falcon 9 has a family of two staged to stage to orbit medium-lift launch vehicles cool so that is our image so essentially we want to be able to say like Falcon 9 country USA description will add that throw in the image click Add rocket and that should add it to the list but let's look at how this thing is working so if we look at our top level component I've got our form we've got our list essentially this form needs to be able to add to that array now one thing you might try and this technically would work but it's not the best practice you could pass the Rockets array down to the form and then just push directly into that array technically that would work but we don't want to do that essentially we want to pass the new rocket back up to this component and then push it into the array because all of the modifications to data here should happen inside of this component it should not happen inside of a nested component a CSS stream would be awesome that would just be me learning better CSS because I definitely need to practice like I mean you can tell from a lot of my streams I use CSS frameworks all the time yeah that'd be good a good like learning stream where I'm just banging it out with CSS stuffs okay so essentially because I want all of the modifications to this data to be done inside of here let's just go ahead and write that so I'll have some methods here this method is going to be add rocket it's going to accept the rocket and then it's just gonna say this stock rockets that push rocket easy enough right and actually I just remembered okay it didn't blow away cool yeah Brooks I would totally be down for a pairing stream I mean honestly I think like if we did a game a gaming pairing stream you would probably be the Navigator and just like tell me what to code I like I've coded games before but it's definitely not my strong suit either but I am down we should set that up very soon so this method exists you can pass it a rocket and it just pushes it into the array so essentially we want to send this method down to the foreign component so that it can call it with a rocket that it creates after the person or the the user clicks submit so let's pass down add rocket we're gonna say add rocket is add rocket and now inside of our new rocket form we now have a prop and that is add rocket and essentially when this form is submitted we want to pass that rocket back up so here's our window on data I'm actually going to have a rocket which we will bind to in the form so rocket is an object it has a name which is an empty string it has a description which is also an empty string it has a country and it has an image like that and actually here's what I'm gonna do I'm gonna create a nice little function that sends us this is this object so get empty rocket right here nice little function get empty rocket just returns that guy I'm gonna use this later so when I want to blank out the form basically I just have to call this call this method overwrite it and then the form blinks out cool so now that we have the rocket on our data let's bind to it in the form so the input here we're gonna say V model is gonna be rocket dot name and then on this one we're gonna say V model is rocket country and then on the text area the model is rocket dot description and on here V model is rocket dot pitch and now I'm actually gonna make this button a type of submit and on the form I'm gonna add a submit event so I'll say at submit submit and we'll prevent the default action we'll say on a rocket now essentially I don't want to directly call this add rocket function because I need to be able to do other things like I need to be able to clear out the form and different things like that so if I were to just directly call that function I wouldn't be able to do extra stuff so I'm gonna define my own method inside of this component called on add rocket which will then call add rocket which was passed down from the parent so on here I'm gonna have some methods let's do on add rocket and inside of here we're gonna say this dot add rocket which is the the prop that got passed down write that method defined in the parent component with this stockett and then we'll say this socket equals get empty rocket so that'll just get a brand new rocket that is totally blanked out let's see what happens so we go over here let's do a hard refresh let's make sure there's no errors no errors show the form Falcon nine country USA image is going to be this thing copy the image address their description Falcon 9 is family team mm-hmm cool it's good enough for me let's paste that in moment of truth so I'm gonna click this button and hopefully we see it down there in the array ok the form emptied out and there it is very cool so it's working that's a lot of text probably shouldn't paste it that much but ultimately this is working so it's kind of like walk through what's happening there so again we start at the top level component rockets it takes a break take a sip of Europe lucre I totally forgot I got an email from a guy named duty he's from France and he told me I've been pronouncing la croix wrong if I were to pronounce it in French would be knock rah rah I think I know it duty if you watch this you can correct me not cry but actually this company is actually based out of Detroit and it's the Lacroix River but it is it's like a French spelling ok top-level components so this is rockets new rocket form has an ADD rocket prop and we're passing down ad rocket so whenever whenever you're looking at a template anything that is essentially the expression that is something defined inside of this component so when I see ad rocket right here that means we're pointing at ad rocket defined on methods so I'm essentially taking this method and passing it down to this component the left-hand side is always the name of the prop so if we look inside of new rocket form it has a prop called ad rocket so essentially this syntax here is saying the prop inside of the new rocket form is going to get the value of ad rocket from this component and now it has access to that method inside of it now essentially what we do is win when this component loads up we have just this empty rocket object and we bind all of those properties to the form so the name the country the description and the image and as the user types this object is kind of getting updated under the hood here and then finally when the form is submitted we call a method inside of this component on ad rocket and again I mentioned before the reason we do this is because we want to be able to do other things like blank out the form so this this dot ad rocket is calling the function that got passed down from the parent we're saying ad rocket we're taking the rocket we defined here passing it back up we're overriding our internal rocket with a totally empty rocket that empties out the form and then one last thing we could also do is hide the form so this fat show form is false so the moment you're done submitting the form hides and we actually just see the list and then if we look at ad rocket that simply takes in that rocket that we passed in and just pushes it into the array boom and if i refresh it goes away because we're not sending it to a server or anything like that but let's just see it one more time named Falcon nine country USA description oh copied a lot more than I thought I did that's why whoa they're copied so much oh I see it's selected on the right hand side I didn't see that can't just want that cool and then we'll grab the image throw that in there click Add rocket the form hides and if we scroll down there is our 9 awesome ok one other thing I want to be able to do is on each rocket I want to have a remove button so you can click remove on an individual rocket and actually remove it from the array now this is gonna work very similar to how we pass down that function to the form in this case we're actually gonna pass down a remove function and then just remove it from the array so like we did before let's go ahead and define that so let's say remove rocket and let's get the rocket will say index is going to be this dot rockets dot index of that rocket and then we're gonna splice that index out of the array so splice accepts the index and then how many you want to remove so remove one from the index of that rocket and that should remove it out and so now if we look inside of rocket we essentially want to have a nice little button here no sorry button and let's do button danga will say delete and when we click on this rocket we want to remove rocket but that doesn't exist so we want this to exist as a problem so we'll put that there but notice rocket is actually a child of rocket list so we actually have to pass it down through rocket list so if we go into rocket list we need to pass down remove rocket here as well and this needs to be a prop in the rocket list also and then now to get removed rocket down to rocket list from the top level component we need to pass down remove rocket there so again it's kind of like this top-down flow we define remove rocket in our top level component it has the functionality that removes it from the array we then take that function pass it down to rocket list rocket list defines it as a prop and then passes it down to each individual rocket and then rocket will call this and actually we need to pass in rocket when we invoke it and so now we pass that function all the way down and whenever we click on it we're passing in whichever rocket we actually clicked that button on so let's see it happen delete gone delete delete delete it works and again this is kind of like that that top-down flow you might be wondering it or does anybody have any questions like why are we doing this like you could you could do this all inside of one component and it would be a lot easier to maybe understand initially we're not passing things around everything's in one place you might have any questions about that I'm gonna take a quick sip really the main idea is modularity maintainability so we could do all of everything we've done in a single file but eventually that get starts to get really really big and then all of your logic is like intermixed and notice like new rocket form it does have some logic right and it does have its own data but that's specific to the form no other component needs to know about the data that's bound to the form or the fact that we're hiding or showing the form like all of that is encapsulated inside of this component so that the outside world doesn't have to do this stuff and so that exists there and then really we can reuse this component anywhere as long as we pass down an ad rocket function we can reuse this component on like multiple pages so that's really why we're not defining everything inside of one big component and similarly for the rocket component we could reuse this throughout our site so this is just a simple component that displays a rocket but you may want to do that on multiple places on your site you may not only have the rocket list maybe you have the individual rocket page you can reuse this component and not have to duplicate your code yeah and then again rocket lists just accepts a list of rockets it doesn't have to make the API request it doesn't care where the rockets are coming from it just gets it as a prompt a prop so all of that logic which actually calls the API is inside of this component and if later on we need to contact a different API or we have a different array of rockets we can still use that rocket list component as long as the list of rockets has the same data inside of it so by like structuring it this way we're making our code for one more readable more maintainable and yeah essentially it's more maintainable and also like if you if you're working on a large team different people might be working on different smaller components so instead of having merge conflicts where everyone's working on the same really big component by working on smaller components and breaking out functionality you can be less likely to step on each other's toes okay let's look at our readme see kind of where we got so all of the state lives in the Rockets component that's a bit of a lie because I did mention that the rocket form does have its own internal state and that's okay with me because no other component really needs to know about this internal state just the form needs to know about this so that's okay with me however the array the functions the calling the API all of that exists on this top level component a question from true in the chat a little he's a little lost on the relationship between views and the components directory and you're referencing ROC Rockets W as the top-level component yes okay so technically I'm not using a router but I might if I were using a router I would have a route that's like slash Rockets and that would load this Rockets top view I'm calling this the top level component because app dot view is really really dumb right it it it doesn't have any data or methods of its own technically app dot view is the topmost component but for the the app that we're building rockets is a top-level component that that has all of that data and functionality inside of it it ultimately views are gonna be where your complex components go so like any component that is like making API requests or is holding on to a list of data or something like that that would go in your views directory and then anything that has props on it and like is essentially just a child component that's gonna go in your components directory and yeah I probably shouldn't be calling rockets our top level component because technically this is our top level component cuz even in here we're bringing in like navbar and rockets and I could also bring in like footer component or something like that but the way I'm talking about it is essentially like the top level of the meat of the app and in apps that you build you're gonna have lots of different pages and essentially lots of different view components that have a lot of functionality like this and then have smaller components that they bring into them hope that cleared things up please feel free to ask more if it didn't clear so really back at the readme all state lives in the Rockets comments so this is like Maine State the array any modifications to the array that lives in the Rockets component data is then passed down as props to child components so if we look at Rockets its passing down the Rockets array and if we look at rocket list its taking each of those Rockets and passing that down to the rocket component so we're passing that data all the way down the treat child components will call functions in parent components so both functions the add rocket and remove rocket are defined at the top level here and then those are didn't just passed down and called from the child components so rocket form add calls add rocket when it needs to add a new rocket and rocket list well actually the rocket component will call remove rocket when it wants to essentially remove it sweet yeah so that's that's mainly it and again this is this is a bit of a trivial app but like all of these techniques can really be applied to any apps that you're building so instead of putting everything inside of one component you can start to kind of break things down to kind of like use this structure now I have been streaming for about an hour I think it might be fun to convert this to view X yeah I think imma do that one interesting thing about view X is like you'll notice like this remove rocket function I had to pass that down to levels I had to pass it here and then I had to pass it here with UX you can get around passing things all the way down by just tapping into actions that exists kind of at the top level so let's do that let's add view X to this app that will be fun I have not done that on the stream yet so let's check out view X gonna find their website so view X is a state management pattern and library for viewed applications so if you have heard of redux and react well Redux is typically used with react you technically could use it with view if you wanted to but view X is essentially like a redux style pattern for your view j/s apps yeah and if we look at their their example here like this is just a basic view app the template has a number on it data has a number and then you have a method that encrypt like increments the the data under the hood thanks Noah thanks for subscribing so this is like your super basic view app I think in here they'll actually talk about how they mm-hmm turn this into a view X app ultimately state is the source of truth so you'll notice how in the Rockets component this is kind of the source of truth for the whole app so like this is the source of truth for the the form because it will add to that array this is the source of truth for the list because it lists out that array it's the source of truth for the rocket component because it's getting the data from there but essentially a view X has you structure your structure your entire app in that way where all of the data lives at the very top and then any components that want to use that data have to use either getters or essentially get the data directly from state so you have your state and that's all of the data of your app you then have your view which is like the template how that's that state is represented in the view and then you have actions which are different things that can change the state based on user input like adding to the array or removing from the array or something like that and there's some different terms in here so the let's take a quick break also collect my thoughts so mm-hmm whenever you're modifying state that is known as a mutation so essentially you're taking something in state and changing it so in our case a mutation would be adding to the array or removing from the array now this is different if you're familiar with Redux Redux does not mutate state it creates a copy of State with the values changed on it but in view X because of views reactivity system it can detect when mutations happen and you kind of get the best of both worlds so mutations will change the state view components will then get access to that state and render out the data and then anytime they want to change the state they will dispatch an action which then makes a commit which actually does the actual mutation so oh I was hoping they would show us this app shown with you X let's see real quick if they do yeah so they actually do so essentially they take this basic view app defined with data and first they define a store and so a store has state and mutations you can think of mutations like methods that are essentially functions that can be called that will modify state so this store is very basic its state has a count variable and it has one mutation which is increment which increments the count and the way that we make that actually happen is if we say store.com it and then pass an increment under the hood that will call this method with state increase the count and then rerender the view to show the latest value the other thing built-in here is getters essentially getters are very similar to computed properties on your component because they can access multiple things and then just return some value to use on your component however let's just use it let's let's get into it so if I going to getting started installation yeah we can install it so actually because I use the view CLI there might be a view X plug-in let's just search that real quick if there's not then I'll install it manually you see oh I three view X plug-in I think like there there should be because in the initial screen when I was generating my app it asked me if I wanted to add UX see we can find it actually look I think honestly I will if I can go into this this folder if I do view add UX hey sweet so that's that's gonna install view X Oh what not found what View Co I plug-in latest was not found well that's lame let me update my view CLI come in how do I install the view CLI NPM view CLI three installed you know that I think maybe I didn't have the latest version probably shouldn't be spending time on this but this would actually be really cool if I could just do few ibux it automatically installs it it'll create the files for us bring it in no it is beta 6 just right now it's broken we can actually let's look at the this github repo and see if there's an issue open for it I think it's github.com / UJS / that what the heck searching on NPM okay maybe this can't be done yet it still is in beta regardless I can just do yarn add UX and then we'll bring it in to our main digests and then use it okay so in our main DJ s right below view we can import view X from UX and then right about here we'll say viewed use view X look at the docs that's how we do it now we can do it so we can do we can create our store and I'm just gonna create this in a file called storage is at the root just like that I'm gonna say export default this thingy and I need to import view X in here you X and now we can get to defining things the mutations for now semicolon okay we defined our store we will also I think need to add it in somewhere right getting started yeah I believe in Maine Jes will also bring in the store let's take a quick break look away from the screen take a stretch take a sip of water okay yeah I believe if we if we bring the store in in here and just throw it on here we get access to it I'm very curious why the docks aren't telling you how to do this because technically his I mean I don't want to import that store into every component most basic view counter app let's see how they did it what I don't want to do that though I want to bring it into an app application structure components store you have your yeah and typically you can split those mutations and actions out into separate files mine's gonna be pretty basic so I'm gonna keep it all in the same let's look at their example here so in my app dot yeah so bring in the store and then put the store on our view instance and if we look at the store let's see what it does that's where we use of view dux they used view X makes sense so let's do that so instead of doing that there we can actually do this inside of our store left import view too okay and so now that we have our store defined on there we can start to use it another concept in the UX is modules you can essentially start to break up your store into separate modules so instead of because it could that also could get really messy if you put everything at the top level but we could have a module for rockets we could have a module for the contact page we can have a module for editing rockets or something like that cool so now if we look at components let's see how they do if we look at the product list it's using map getters and map actions from view X and if we look at the store and we look at the products its getters some complex stuff let's figure it out though okay so essentially the state of our application is that array of rockets so I want to just say like rockets is an empty array right and then I need an action I essentially need an action that's actually going to call the API and then I can fire off that action from inside of my component so let's create a get Rockets action let's take a look at actions in the docs so it gets access to the context mm-hmm and essentially here is where you want to do like a sink get Rockets and before I go any further let me go ahead and commit because I haven't modified my components yet and then we can see the commits kind of before and after I added UX because I'm going to be ripping things out of the existing existing app initial of UX cool hmm so yeah so right here if we look at our Rockets component mmm when it's mounted it's directly calling the API now that we're using view X we don't want to do that either so essentially I'm gonna pull that API into my store and then I'm gonna have an action here called get rockets that accepts the context and this will actually call the API so I can move this code into there so I'm gonna say rockets equals a weight that get Rockets and this will be an async function and then I need a mutation in this case my mutation is going to be like set Rockets and this will accept in I believe if we look at mutations it can accept in a parameter yeah so will accept in the rockets and here I'll just say state rockets equals rockets and here is where I want to do the commit so I'm gonna say context commit set rockets with rockets hmm assignment to a property function no pram reassigned what when adding new properties I am just gonna ignore this lot yes Lent ignore this because I want to do that so disabled yes lint for that one line and then reenable it so essentially what happens is when we call this get Rockets action it's actually gonna make the API request when that API request is finished it's going to commit a mutation to set the rockets and then this is going to set rockets on our state okay hmm the other thing we need our getters so essentially instead of directly accessing rockets from the state we want to call a getter that just returns the rockets so it's okay get errs yeah we'll just have getters here and we'll just say rockets and a getter we'll accept the state and we want to return state rockets hmm cool [Music] that cool okay so we're doing some stuff it's it's all gonna make sense very soon so now inside of our component when it's mounted we want to dispatch get rockets so let's look at actions and how we call them will say store dispatch and so on this component here when it's mounted I'm gonna say this dot dollar signs store dispatch get rockets okay let's see what happens and if I've broken anything no such file or directory what puny code why are you complaining main bjs what am i doing in here so I'm bringing in the store if I look at storage is it's exporting a view X store something's happening no such file or directory this is very curious it's like ionic stuff let's just see what they say well you know it could be earlier when I was having that issue when I tried to add it from view X like if we look at our package.json we do have view X as a dependency yeah I'm gonna oh oh I think I think that's what it is okay so for whatever reason I have a package lock JSON let's delete that and I'm gonna totally clear out my node modules and then just do a yarn from scratch yarn yarn install from scratch I think it was like yarn and NPM install conflicting with each other okay now we will yarn yeah we will nvm oh no now we will yarn run serve I said giving us the same error Oh components listed should have explicit B keys okay so I think it's working now that was weird okay but however so nothing showing on the page but that's because I've moved everything kind of into interview I guess I don't have the view dev tools I'm gonna go ahead and stall those few tools because the view dev tools actually have a view X log and debugger in them so we can see all of the actions and the commits and everything happening inside of view X we can see that in the store in the dev tools still hard fresh hard refresh UJS is detect on the page where is it close the dev tools reopen the dev tools there it is and switch to view X okay so you'll notice you can see our base state let's do a refresh not seeing the commits though interesting regardless our our our call to commit is actually working okay so we're the the store is getting the Rockettes because in our component we're saying dispatch get Rockettes cool next thing instead of having data we can essentially just get data from the store and we'll do that inside of computed so I'm gonna get rid of data here and computed is an object and essentially we want to take that get er right there we go there's that mutation but we want to take that get er it's decide and defined inside of UX and call get rockets so that we can actually just use that inside of the component so if we look at the view X docs on getters we can use I believe map getters yeah the map getters helper and essentially that will call that getter function and set it on a property inside of our component so we're gonna bring in map getters from view X and then here we can call it we can say computed we'll just we'll just directly call it so we'll say map getters and we're gonna say Rockettes is the get Rockettes getter and so now on this component we are creating a computed property called Rockettes that's directly equal to the return value of get Rockettes so now just by doing this we are grabbing the Rockettes out of the store and we should see them on the page maybe we don't oh is it just called Rockettes not get Rockettes let's see Oh which I did just call it Rockettes that's why so if that's the case I can just say map Gators with rockets boom so it works so we've essentially moved our state and are calling the API into a single place now comes the interesting thing so these these two things here add rocket and remove rocket I am no longer gonna directly define these on my component I'm gonna get rid of them gone totally totally gone now in our store these are essentially going to be mutations right because they're modifying state so in our mutations I'm just gonna add these in here and then we need to update them so add rocket is going to accept the state and a rocket and then we'll say state dot rockets stop push and then remove rocket is also going to accept a state and a rocket and instead of this start rockets will say state dot rockets and then we'll do state dot rockets dot splice so now these mutations are directly modifying the state here but where this gets interesting now instead of having to pass down those methods right because before we were directly passing down ad rocket now we don't have to do that anymore and here we were directly passing down remove rocket we also don't have to do that now inside of the rocket form we can have direct access to that mutation and just call it from there so let's do that let's look at new rocket form and here instead of saying we need a prop called ad rocket now we will just say this dot dollar signs stored commit ad rocket and then pass in this star rocket done and so now this component is able to essentially reach into the store and in send it a value instead of having to pass down props so let's make sure it works if we take a look at this so we're gonna try to add the Falcon 9 again so I'll say Falcon 9 country USA description is a rocket and then the image is this image add the rocket notice the add rocket mutation got called and I can actually click on this and I think I should be able to see what got passed in so the payload was that rocket from the forum and then that got pushed into the array and so now we see it there very cool here's the other interesting thing about view X though now that we're keeping track of all these mutations I can actually go back in time if I click this base state I've now time traveled to what the state looked like before that mutation and then I can actually go back to this mutation so this is really great because you could actually do things in production where let's say a weird bug is happening for your users so like you turn on mutation logging and now they can actually send you their mutation logs and you could literally click in here to see state and see everything that gets changed and really see where the bug is happening and how to fix it which is pretty sweet time travel debugging look at me Wow cool so that's for adding the rocket now comes for removing the rocket so if we go into the rocket component notice before it was accepting remove rocket as a prop we don't need that anymore and then also in the rocket list we don't need remove rocket anymore it just needs rockets and we don't need to pass down remove rocket but now inside of rocket we can just define a method that come that commits remove rocket so we can say methods here and actually is there like a I think there's a map mutations maybe yeah Matt mutations awesome so instead of having to define a method I can map the remove mutation from the store and just call it directly from the template so let's do that so inside of this component I'm going to say map mutations and then here I'm gonna say methods are going to be map mutations with remove rocket cool and so now that I've mapped this mutation remove rocket I can directly call it in the template and this is actually calling the remove rocket mutation in the store all right let's check it out so if I click the remove button gone gone gone gone awesome and notice each one of those mutation that was logged and I can like go back in time so I could go back to the first one and now the state is back to the way it was before I remove that one or I could go back to that one or that one or that one which is pretty freakin sweet yeah and if we commit the mutation it gets rid of all the mutations after it it's so it's like they didn't happen but this has also kind of like cleaned up our code right so like in our top level component it is essentially just getting the data from the store and when it's mounted it's dispatching to the store hey go call the API and get the data and this is just listening so when the data comes back from the API it'll automatically be usable technically I really don't even need like map getters in here I could technically put this map getter inside of rocket list right because rocket list is the one that actually uses the the stuff let's do that why not so instead of passing this down as a problem let's actually take this getter here and put it on rocket list like that I'll have to bring in map getters in there instead so rocket list will bring in map getters and now rocket list has direct access to the store to get the Rockets but it still makes sense that this Rockets component is actually the one that's firing off get rockets because it's kind of like the these are the brains of the operation and then the rocket list will just be listening for that and we'll show the array yeah so when the app loads up the top level component fires off gets get rockets and then this rocket list is just listening for when that actually has some data on it and then is using it and then passing it down awesome okay so that is kind of like view X in a nutshell essentially it takes all of the state all of the mutations of the state all of anything that's happening with state and puts it all in one place and then anywhere in our app where we need to use that we essentially directly call the store to do that thing and this this actually makes our code a lot easier to maintain because we're not modifying State in random places and we're not passing props everywhere everything if we need to update it happens in this one place and anywhere where I see a commit I know that they're calling a specific mutation in my store cool I think that's it I have been streaming I think for yeah close to an hour and a half now I am a little bit exhausted and hungry so me go eat dinner any last questions thoughts comments criticisms in the chat happy to talk about absolutely anything and we'll go ahead and push up this code so you can take a look at it as well oh yeah let me fix these V bind keys real quick so this before I need a key let's do the key is rocket name yeah cool I got rid of that air say update to use your ax to use your X push gotta set my upstream cool so as I mentioned the code is all up on github if you tuned in late you can go to github.com slash codeine garden the link is also in the description below but this repo has all the code that I just worked on let's take a quick break before we end it all hmm so it has all the code and if you do look at the commits I probably should have done this on separate branches but you can go back in the commits to see what it looked like before view X and what it looked like before we built it all out thanks everyone for tuning in I will mention real quick a few things so if you visit coding garden you can see my latest stream schedule so this will show up in whatever your timezone is oh yeah true-true says he hadn't seen view X in action yet it is pretty awesome I actually don't use it as much and let me move myself out of the way so you can see my schedule yeah I don't use it as much but when you're building larger apps it makes a lot of sense because it moves everything into a central place it gets a lot easier to manage but if you visit coding garden you'd see my streaming schedule I'm trying to stream at least once a day this morning I did morning tea check out that if you have not seen it yet right now we're at the 620 stream all of these are in mountain time but if you view the app on your page you will see it in your local timezone also if you visit pull coding garden may need to login yeah so you can suggest new videos for me to make again let me move myself out of the way just make myself tiny actually this is great watch me float around the screen but yeah poldek coating that garden you'll have to log in with Google that's mainly just so I don't have people spamming votes but you can suggest new tutorials walkthroughs livestream topics and then vote on them if you click the heart you will vote on that specific topic I think that's it don't forget to subscribe I'm really trying to get to a thousand subscribers I can start to monetize the channel and do this a lot more often thanks everyone for tuning in live wait let me see J 3 alright thanks for tuning in live see you next time
Info
Channel: Coding Garden
Views: 8,206
Rating: 5 out of 5
Keywords: mechanical keyboard, coding, learn web development, educational, vscode, learn javascript, web development, debugging, node.js, html, learn node.js, backend, learning, full stack web development, learn to code, how to code, frontend, beginner, full stack, lesson, live streaming, javascript, frameworks, debug, css, programming, live coding, full stack javascript
Id: lRE03MBZnuY
Channel Id: undefined
Length: 89min 45sec (5385 seconds)
Published: Thu Apr 12 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.