[Live Code Session] State Management in Web Components Explained

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey what's up everybody hey MP here and today we're gonna shoot a video it's gonna be a live coding session and what we're gonna do is build the world's sweetest counting app the obligatory counting app because what we're gonna talk about is state management so tons of state management libraries out there we had a great discussion down at hacks camp in Durham North Carolina last week where we just went back and forth with the different state management libraries state management methods do we need state management at all some really great discussions from that from those discussions came mob X and I did a demo of mob X have built a very simple counting application using mob X and actually using a brand new tool from the folks over at Dobby that's a custom base class that allows you to print mob x state and right inside your web components manipulate the state of mob x right inside your web components extremely easy takes a lot of the ceremony out of writing mob x in your in your web component so we're gonna start from scratch let's get started create a simple index.html some stuff in there we're going to say why my sweet counting app and the first thing that we want to add is our hacks app so I'm sorry not hacks that it can be hacked at but in this case it's going to be the count app count app so with web components what's the first thing you need to do is you need to import those using script with type equals module and we're gonna import the scripts AS file let's create that file scripts j/s and inside of that file what are we gonna import we're gonna import a file called count app is let's create count app dot yes and it's going to be a little iment so all the time I have to do this it's go over to lit element go to the getting started templates and grab an example I really need to add this to my snippets but for now let's just do that we're gonna add count app extends from lit element it's going to render our count so it's gonna render this dot counts is with it so I want to show the current count of the application now lit element is not just gonna know where that value came from you need to register it as a property static get properties and we're gonna return an object that says count is a type number then in the constructor super first off before do anything and set count equal to zero so what's the initial state of count so this is an example of setting a local state value so the count app is a web component it has a local state of count the local state of count equals zero let's go on there we go my sweet counting app and instead of my element that's gonna be count app count that count count up it's gonna be there this cryptic module count app goes there why aren't you working why aren't you working why are you working that's debug here lit element must have references aha of course so let's do unpackage this is gonna be the quick and easy way let element and we're gonna specify to load it with the module flag cool we now have our count app and it has count now what happens if we said 210 of course she changed the local state it's gonna render that local state there perfect everything's fine everything is hunky-dory now the problem comes in whenever we need to do this so count app also needs a count toolbar naturally it's gonna tell the user how great they are so to count toolbar count toolbar is going to have the same local state it also is going to know about count it's just gonna do something a little bit different it's gonna say hey there user you have a count of yeah it's gonna say a equals 10 and then we're going to add import the toolbar and use it in our app here count yay everything was good here I'll I know that you probably anticipate what the problem is gonna be and that's whenever we try to change the state of course because whenever we add this new button increment counts it's gonna be this little plus sign and we say that whenever you click it it's going to change this dot count by incrementing it and to do that we need to wrap it in a function okay so this is a quick and dirty way of altering the count here right from the render function added a button that whenever you cook it it's going to just add 1 to whatever the state of this dot count is so whenever I click it it's gonna increment it but oh boy that one's not showing up so what are we going to do what are we gonna do so naturally what you are going to do is you're going to use the platform this is what we always suggest use the platform web components use the platform so the platform would be slightly different than this same idea but you would say increment count as a function inside of that function you would say increment counts which is a function that not only changes the count okay so not only changes the count but it needs to notify everybody in what the count is and the way that it does that is it does this it says this dot dispatch event right all right dispatch event in a dispatch event we're gonna dispatch a new custom event this custom event is going to take two arguments here it's going to say what's the name of your event and I'm gonna say count changed and it's gonna say what are the details of this event and I'm gonna say well the details is the count is set to whatever this count now is so that's what's going to through so basically the way that web components work the way that component architecture in general works is props down events whoa props down events up so in this case we have an app that's changing the state which means it needs to throw an event that that that goes up which would allow higher-order components to catch that event that will then send the props down to their child components to change their state so that's the way that component architecture works with handing values back and forth that's how this tool bar that's kind of totally separate from this app that's how it's going to know what's happening inside of this count app now some pro tips here whenever you're dealing with web components generally speaking you're gonna want to set bubbles true you're gonna would say cancel Bowl to false generally you can play with that and you're gonna say composed to true so what those mean are that's gonna help this event pass up through web components even web components that are shadow Dom's so it's gonna allow your event to pass more easily through this maze of components so where does this effect go how does this help our toolbar at all what we would do is in the constructor of our tool bar or in the connected callback whichever you would say window dot add eventlistener dot count changed so we're listening for the count change event to pass the whole way up through our Dom to the window and whenever it does we're going to call a function in here we're gonna save the I want you to call that count changed function and we're gonna bind that with this so what that's gonna do is it's going to call a new function here that's called count changed which is now going to be sent event and we're going to send count changed the this the this reference so the reference to that correct this or else it'll get confused so what that looks like if you consult log that you should see this in action cool so our custom event is firing it's getting all the way up to the wind though the highest level of the DOM and it's letting our toolbar know that hey something's changed and you can find out what the new count is in the details so it's up to you to update your local state I'm not gonna do it for you so we say okay fine we will handle that that's not a problem we're gonna save that set this dock count our local state of count to the event detail dot count so this is the new changed count so when we do that you should see that hey we just successfully handled state management on our own using the platform hallelujah high-five okay well that's fine and that's totally doable and I would recommend you do it that way until you start running into issues of scale so until you start writing lots and lots and lots of these event listeners until you start getting confused of which event listener should I really tie into I mean account changed could not be the only change event for a count it could be count change count is in edit mode something is editing but don't the count but don't change yet but let the user know that they can't edit it in your tool bar but because it's being edited and they count two worth what you're talking about is adding lots of different versions of what your state is each one of those versions would probably result in a new event listener that you would have to be on the lookout for and I'm not even going to mention how you have to clean up I am going to mention it but whenever you add these events event listeners each one needs to be disposed of so you need to say disconnected callback and then you're gonna copy this and you're going to say remove event listener so you need to do that with every single one or else what's going to happen is you're gonna start you in this app it's gonna be nice and crisp nice and speedy and as you stay on the page long enough navigate through pages long enough your site is gonna start slowing down and that's because there's gonna be so many events attached to the window that it's gonna start slowing down okay so let's say that you have reached this point and now you're on the market in the market for a new state management solution let's see what this how this could be replaced with mob X and improved with mob X this developer experienced rid of all that I'm going to get rid of this custom dispatcher now I'm gonna add a new file that's called store and with store I'm going to so with store I'm going to import from mob X a few different functions I'm going to import to start observable decorate okay yeah we'll get to that before I implement any of these functions what we need to do is we need to set up a new class and this class is going to be our store so whenever you're researching state management solutions they often refer to this store and the notion that there's really three pieces of state management there's the store there is the view layer or the render layer and there is an actions layer and what's gonna happen is the store is going to be in charge of notifying the view or the renderer to update itself whenever things change in the store and the only thing the store needs to do is listen for new actions so in your view layer what you're gonna do is whenever the user clicks the increment count button that's not going to change anything locally that's not going to just reach out and change the count no no no it wants you to release an action this action will be called count increment count the store will catch that action it will know what to do with it it will change the correct property in this store which will notify the renderer and it's the circle of life everybody's happy and then it's not going to be collisions all over the place so that's ideal that's called unidirectional dataflow mob does all that but it does it in a much more a much more magical way so there's a lot of things happening inside of my back's that you're not aware of that it's doing on your behalf whenever you write redux you are writing that whole process out you were explicitly painstakingly specifying each and every step in that process so mob X sort of took the different direction of saying can we hide a lot of that functionality from the users so that you don't immediately want to vomit whenever you start implementing a state management solution okay that being said mob X here's where we're setting up the store so we're gonna set class store we're going to find a new class that's called store and the only thing that we need to set in here is what's what value do we need to start tracking in this store we're gonna do that in the constructor of this new class and the only one that we're gonna track right now is this duck count right we're gonna set it with an initial value that is zero and now we need to decorate this store so we've created the class but the class by itself doesn't really know how to do any of this magical functionality that's where the decorate function from mob x comes in now before I show you how I do it there are two different ways of doing it there's using it the the brand-new es7 way I forget which what you'd really call it with what are called decorators and decorators are where if you've ever seen an @ symbol with like something written over top of it that's called a decorator and it's really just a way for you to write less code so instead of writing observable on like here or something like that what you would do it say decorate store past at the store class that we just made and give it an options object that is what do you want to track well I want to track the count that's in there how should it be tracked it needs to be in observable there are a few different ones there's computed in actions which we can take a look at and a little bit but for right now the majority of what you want is our observables this is a state that needs tracked in a central store and updated in all of the the web components that are subscribing to it okay so we've done that decorated it we just need to export it I'm going to export the Const of lowercase store and this lowercase store it's going to be an instance of our new class new store so what we're going to do is we're going to have all of our web components pull in this store value which is an instance a singular instance of our store it's going to pull that into every web component that needs to interact with it so let's do that let's go to the app we're going to import our store and we're gonna import the store property now what do we do well before I show you the cool base class let's see how we would traditionally do it with with mob X using something like lit element what we do is it's we would give we would have people import the store which we've done but then we'd have them import this magic function from mob X called Auto run and what auto run is going to do is it's going to sit right here and either the constructor or the connected callback and we are going to subscribe to changes of count in the store so we're gonna say store duck count equals this dot count so what that's going to do is say I want my local property of count to reflect at all times the value of store count okay so I'll do that and and whenever I was talking about the magic of mob X this magic autorun function is just gonna know that I'm accessing the count property inside of the store and it's gonna add listeners for that property specifically so you don't need to have to worry about it auto run just sort of figures it out which makes it pretty magical and saves you typing okay so we're gonna do that we're gonna do something very similar to to toolbar I can do something very similar again to the exact same thing it's doc count equals this side count so fingers crossed that's not working let's see why it's not working store count store to count on a run on a run I wonder if it has to be in the connected callback oh count to a bar hmm oh right of course so we are subscribing to the initial value of the store but our increment function does not tie into the store yet there it is let's fix that so in our increment count instead of saying that this dot count equals our change to count we're gonna say that store count so remember I was talking about that unidirectional data flow what I was spacing on is that for this whole thing to work you're not gonna just change the value of count locally no you're gonna change it in the store the store will then tell your local value window update and then the whole circle of life is fulfilled so now if I increment it should be rosy that's awesome now the one thing I will say that this kind of stinks a little bit is that we need to dispose this still this is not this one thing is not a free ride we need to say this dot disposer and still and our disconnected callback we need to call the dispose dispose our function on that so similar to the built-in functionality of adding and removing event listeners we need to add and remove the auto run function now once you've done that this is pretty nice because now I can add a new piece of functionality to the toolbar let's say that I need to add a reset button and whenever you click it on click whenever you click it it's going to say store count equals zero okay that should just work now right out of the box perfect that was awesome can you imagine if I was trying to add the reset I would have to then dispatch a new action make sure that everybody knows that I'm reset what eventlistener name I'm using hopefully I can reuse the count change event but maybe I can't maybe I need to set it send up a new event that's saying the count about to change so once you implement an application using the platform you'll start running into this and you'll you'll realize that you know maybe I should take a look at the state management stuff the estate management libraries maybe they can make my life easier okay so that's great and and just to just to illustrate the mob ex way of running a store what if I don't want to have these changes just specified locally what if I want to specifically say what increment count is I mean in this case it's kind of trite because we are just incrementing it by 1 but that could be more complex logic so maybe when we want to say oh I know this is a good example here we go so increment count what about decrement count okay that's something where if these functions of Tobar will want to use that this app will want to use that but it's not going to just be decrementing it here let's say let's set it and see what the issue is gonna be hopefully you can guess what the issue is I hope I'm spelling this correctly I'm probably not but I'm not gonna worry about it okay so increment increases that infinity decrement is gonna decrease it infinity so what is that gonna look like okay that looks great reset I go to do oh no no no no no no I can't do that there's no such thing as negatives in this application so what am I gonna do because the toolbars are gonna want something pretty similar to that it's gonna want to say you can decrement and you can reset it you can't do you can't increment maybe you can but you know for now let's let's say that there are two options okay so both of these should be able to decrement I should be able to just do that right let's see if that works yep so that works okay so this is an example where my store needs to handle that functionality it's not an observable per se but it's a it's a new method a new action that I need to control so inside of my store I'm going to add a new action I'm gonna say set what should it be able should it be what should be I'm gonna say we're just gonna call it decrement count it's gonna be a function this function it's going to be really simple it's gonna be returned the decremented value of this dot count but wait a second we need to know if it's zero because if it's zero if this dot count equals does not equal zero or better yet if it's below one then or it's only gonna work if it's above zero so if it's above zero then we can decorate it or we can say this dot count is equal to the decremented version of this dump count right so now what is this it's not an observable when you decorate it down here we're gonna say that this is an action this is an action I'm gonna say decrement count is an action okay let's see if that works so now instead of decrementing the count with this decrement I'm gonna say store dot decrement count and I'm gonna put that into a function or else it will just run immediately and that is not what I want okay decrement count let's go come on this should work Hertz works ah it worked awesome so it's not letting it get the value but if I do that I'll see you can you can see where I'm going with this so keeping that functionality in sync can be challenging also that's where state management tool and specifically Bob X really shine just throw it in the store make sure that everybody's using the function that's in the store because everything all the functionality all the logic for what this thing should do will be will be held in that story okay let's keep going with this we'll say this dot pair I'm sorry or you can say store dot decrement count now this works this works this networks reset works voila everything is hunky-dory perfect thank you mob X you're making our life easier now can we push it even further yes we can because what we can do is you can get rid of some of this stuff so you see how we have to set local states of all of the values that we want so if we're interacting with count and these two web components and what we have to do is we have to create local instances of that property in inter and and bind the store the property that's in the store to these local instances it's okay it's what we've been doing um I if it's the only thing we had then then that's great but luckily the fine folks over at Adobe solve this problem and solved it with a new base class called mob xsplit element oh okay so it's at Adobe / lit - mob X they haven't cut a one release yet but it's still something I recommend you checking out because it makes your life super simple because what you can do is extend from not lit element but mob excellent helmet and you can just get rid of all this stuff you can get rid of the constructor the properties and no longer need a local counts you can get rid of the connected callback the auto run the disconnected all that jazz and what you can do is now say like store count increment that get rid of these you see how clean that looks see how easily readable that is I don't to create local instances of everything that's going to confuse people I'm just literally getting to the store getting to the functions I need getting to the values I need and putting them right in the render function so there's no discount there's only store to account really really helps simplify things here so everything works perfectly let's finish this off by taking it to the tool bar get rid of all this stuff you're a disconnected so long care of any thing that says this duck count it's only stored count now and bam you have just created a really super sweet counting app that you can now start tacking on new piece of functionality knowing that you have this nice mob ex store that's going to help you out with all your state management needs so I will push this up to the github repo it will be located at github.com slash it's called mob axe hacks camp mob ex demo so push it up there so that everybody can access to it and yeah I hope you like it I'm really impressed with this workflow it's really taking state management boiling it way down just making it very digestible to the average user and I'm really excited to to code new things with it so hope you like this video give me a shout if you have any questions any suggestions I'd love to hear from you [Music]
Info
Channel: Michael Potter
Views: 4,669
Rating: 5 out of 5
Keywords: web components, state management, mobx, lit-element
Id: QpzpMUKI6fA
Channel Id: undefined
Length: 37min 47sec (2267 seconds)
Published: Tue Dec 10 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.