#1 Angular Belgrade Meetup - NgRx Component Store by Alex Okrushko

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
uh hello everyone and welcome to the first angular belgrade meetup uh today we have one very interesting talk about ngrx components stored by alex okrushko but before alex starts his talk i'll first introduce you our angular belgrade group so i founded this group with few goals in mind first goal is to build angular community in belgrade and serbia in general second goal is to have a place where we can share our knowledge about angular arches typescript and all other angular related stuff and third goal is to help beginners learn angular if you want you can follow us on twitter and linkedin you can also check out our github profile where all the sources from our meetups and workshops will be available and you can contact us at angular belgrade gmail.com if you want to speak at the angular belgrade meetup you can submit your talk at the following link and don't be shy if you have something cool to share with us feel free to submit your talk and okay that's all for me let's go back to the main topic for today so ngrx component store is the latest library from ngrx family and it's used for local state management alex is one of its co-creators and he's also software engineer at google angular toronto organizer core member of ngrx team and then jrx maintainer at google hi alexand thank you very much for joining us today hey all uh thanks thanks for having me uh that would be some surprises i guess during my presentation as well so that's all good uh all right let me just do this yeah a little bit here good good good yeah you can start now stage is yours thank you um all right so um [Music] so i'm going to be talking about a component store which is the latest uh library in angular in angular and in grx that i think would unleash the whole uh new patterns and um and and you it basically empowers you to do state a little bit differently right so up until certain point up until now we had you know global state management libraries like ngrx and that's what interex is known for right the the interex store which is actually used in one of every six applicant applications worldwide it's uh it's by far the most popular and then there are also different approaches like behavior subject or no state at all right this basically some sometimes state is just like it happens to be a certain place so it's there you know and you know it's not a lot of thought given to it so i'm going to talk about some of the state issues and how we can solve them today so if you by the way if you have any questions uh feel free to throw them in the chat i'll i'll be i'll be monitoring as well i'll be very happy and excited to actually answer them i use this opportunity of having this live discussion and again i'll be watching them so feel free to drop drop questions here awesome all right so so i got already introduced uh there's a little bit of change so i'm i'm switching to from from google and firebase i'm switching to cisco now uh so i'll be there as a principal ur architect at cisco for the customer experience uh products i still am uh the ngrx team member so that doesn't change i'll be participating uh still keep participating very actively there and uh angular toronto is what i organize uh so i'll be happy to have uh have you watch it or have you you know present there as well if you have an interesting topic so please reach out to me and other thing is like i really like this in-depth depth resource so um do check it out as well if you have time this is uh this is uh where you know a lot of great knowledge was shared over years so and it still continues to be so check it out all right so this is the fun part uh if anybody knows who this guy is anybody knows yes uh albert einstein so he had this famous quote right and his quote saying synchronizing state within the application and the back-ends is one of the most complex tasks that developers have to solve and you're like he never said that well you're right you're right he was before the internet so he never had the problem of this state he had different problems with state but if he was with us today i'm sure this is the one he would have said synchronizing state is really a problem and we solve as developers solve this problem whether we want it or not whether we're explicitly facing this thing and and and having those uh state flow diagrams or not right in any case we do have state in the apps that and we have to deal with it but what is the state some of you like and what is it we're trying to manage because those state management libraries they're managing the state right so to understand what we need to manage right let's first understand what the state is so what is the state uh and again there's multiple ways to split it up i really like something that uh that i first saw from victor sofkin so the way the way what i saw is there are basically two types of state right there's two kinds of right this is in server there's one state and there's a web app there's another one so for now let's assume server just has some kind of back end state what we're more interested is is the web app state and we have a few kinds and the ones we'll take a look in today is persistent state url state client state and local ui state so this is the one they'll be taking a particular look in today and this is very important i think to understand what those are because managing the flows of them is what the main problem is so what is the persistent state persistent state is the state or a snapshot of a state that we get from the back end or we persist back this is our json that we get back right those are all our requests and responses that go there this is all our ajax right so this is a persistent state we're persisting it to the back end it's being saved at the back end and we're actually getting the snapshots back as well so this is a persistent state then we have one very important other state a url state and this is the state that drives so much in our application it's so critical to get it right this is the state of our url and the router so sometimes that means the router as well or the data that it has so that's the other one second one is the client state client state the way i like to think of it is uh something that is important in the scope of the application but it's not persistent to the backend so it's it's it's state that app is application aware right for example in this case which tab is open so applications very well aware of which tab is open but it's it's not persistent to the backend right we're not saving to the back end which tab the user has open so that's the client state and then there is local ui state and local ui state is the state of this for example a slider button right inside it takes some kind of input probably but inside it's completely encapsulated it's just reflects it in the ui right for example is it enabled or not the button can show you but button has is not no awareness uh what it doesn't mean to be on and off all it does is just like oh i'm on somebody clicked on me okay and now i'm off right and it just communicates that to the parent components so those are very frequently like presentational ui would be your local state could be more more in that in those lines so managing these states is actually pretty hard and especially if your application is very functional where there's a lot of things happening this this is where the most problems come in uh error handling as well and some of the race conditions like those are the things that and those all those state flows how they're going back how they shared through other components all of these are one of the most complex tasks that we as developers have to solve all right so that's that and we have some help of how to solve it we have angular angular is really good angular is on a punitive framework that provides you know a lot of uh batteries included for us which is you know it provides us the forms it provides the components it tells us how to do the pipes you know it even provides us the services right it has its own http client so a lot of things are like it's opinionated we do things with a certain way we have ng modules and things like that but is it though is it opinionated enough and this is where i think we have this great opportunity or we have this within your x because ngirox saw this opportunity where angular was not opinionated enough for example yes we do have services we do have services but anything with the state management i think angular still wasn't there it wasn't providing those things so it wasn't had no quite an opinion on one of the most important tasks that we need to solve is those state flows so we kind of i think we kind of solved it within your x and we'll see today why and we'll use it's an example there's a very simple application that has basically three pages right uh the first page is you know that's just a list of products that we have uh then we have you know once you click on the product you have a product details page so it has more information about it this is where you can add things to the card for example it has description and things like that i noticed the card there on the top right and one finally once we clicked on that card uh it shows us what we have in our cart for example we have here three different types of products but four products in total we have two of for example sheet music so quantity also is included here right so every time we add item to the cart we get it here awesome so we have that uh let's start from the one of the most basic components that we can have here let's start from the car icon this component needs to know what it uh what what to show right it basically needs to show how many what's the count of in the card right and this component can be completely presentational and then that way you know it just gets it through the input and it has the car items there as its local state so it it just uh but then we have to have container component that provides the data to this presentational card icon the other approach we could take is well we can make this already more aware of the client state and for example you would get or actually this case would be persistent state in this case uh you will just will inject some kind of service into this component and in this case it would be card service and the card service uh has this get car product right call and you can see by by having it a pipe right this gives us some information that's observable already and we transform those car car products which we could be an array of things right with the map function a map operator would transform it to a single number right so we'll have observable of numbers so we change it it's now a reactive thing so it's now an observable great so we have that how does the card service look like well in this case cart service is something we call a a pool based service it exposes it has no state it's completely stateless but it has a bunch of methods in this case this method is the getcar products which returns us an observable of those card items right and then remember we pipe it through a reduce reducer function there to get to actual number but what what's it's interesting here the get card products returns you as observable back right so every time you need you want to get the need new data you call this method the get card products and it'll just give you that information so in a way we need to pull the information from the card service this is a pool based service and it's again completely stateless uh remember that state because we'll use it uh soon as well later on great however you know the uh the data here is a little bit more interesting than just getting it once from a service let's take a look how our app is structured like component wise so we have this car icon component right that we saw it itself is part of the uh header right then we have a bunch of product uh car product components that we have there and again it's very oversimplified even for this application so we have a bunch of car products all right uh and then these car products are part of cart page we'll skip the buttons and stuff at the end of it we have a router outlet that handles it so header stays the same while router outlet changes from page to page this is the structure that we have and finally the whole thing is in the app so this is how our app is structured right let's take a look at it uh and have it and as a component to component view all right so this cart icon information is needed our card items how many card items we have or what card items we have is needed in two places we need it in the cart icon component right and we also need it under the current page component so this way we need it in two places how can we share that data across well one of the ways we can do it is we can have a cart service that provides the data to the app where basically you find a common node the first comma node between these two and then just you know through the inputs just propagate it down you would rightfully agree right away that hey this is wrong that doesn't feel right now our card item is just spread throughout the entire application and now every component needs to pass it on even when it doesn't use it like hatter in this case doesn't doesn't care what we're passing like and now you know refactoring or changing anything becomes a problem testing becomes a problem a whole bunch of problems so there are this approach is uh bad on many levels and we definitely don't want to do this so how can we how can we do this now well we can have a service that's basically injected into two places right and you know we have the get car products we call one and we have the gear car products car items you know in the in the car page but now i have a different problem uh we are we need the same data but each component would ask it independently which would result in a few network requests uh for the exact same data maybe even at the same exact time so how can we solve this how can we make sure that we're not duplicating equity network requests and again there are multiple solutions uh let's look at let's take a look at one of them one of them is to expose the scar items as an observable so it's still an observable but now it is the property in the cart service and what the one would do this well we'll initialize it with this data so we'll get the car products and that will share replay so what the sherry play does it will share this information between those two components right so they can just listen for the car items themselves and it won't make i won't make those repeater requests so just do the request once so our cart service now becomes stateful we have a state so read only cart items here is a state in the service it's no longer stateless we have a state how we consume it well instead of calling the get car products now we can just you know listen for this observable and once they emit something we'll push it through this map and we'll get our count so this is one of the approaches and it works in some cases however it doesn't work in some other cases in our case it won't work and why doesn't why doesn't it work in our case well it appears that our car products data is not static it's dynamic and we can change it within the application let's take a look so first of all you can remove items from the cart you can purchase car items you can remove everything right so that affects the number of products that we have in the car moreover we can add more items right so that data is very dynamic there's multiple things that you know can affect it on different pages we definitely don't want and how can we solve this we definitely don't want our car icon to be concerned of what's changing the data right we we want it we want car icon just to reflect the changes we don't want car icon to know what's changing the data is that they add to car button click is it remove click we don't want car icon to know who's doing it we just well and let it know that it's something did so we we already moved from push based to pool base from cool base to push base so we are no longer asking it but we now are listening for this property how can we make sure that this property now reacts to those changes so the way we can do it is something is called something is known as service with a subject approach or reactive service or service with a behavior subject or observable service there's many many names for it but in a nutshell it's the same thing in a nutshell we have a keeper of a state in the service for example in this case it's the cart items subject it's a behavior subject so it needs an initial data for example in this case would be just empty car item array so now that data could be changing over time and the way we expose it we still involves the subject itself is private but the way we expose it is through those read-only property of car items right so we do that subject dot as observable and that exposes it as an observable so now you can start listening for things in it but you can't push it anyway so we have the state state is still encapsulated in the card service and it's very important that it stays encapsulated right so consumers can read if consumers want to change anything they'll have to call methods on it and in this case we have the add product method for example they'll take the new id right and they will do this post request so similar what we was doing before however in this case it no longer returns you an observable it returns your void right this method returns your void nothing you can't re it doesn't return anything in in another word so that's the post it subscribes right away and it pushes this value that we get the new array of those items into the subject and then what happens subject reacts with it right so it's an observable car items get updated the new value is pushed through the system so how would we consume how can we consume this thing well we're still listening for the card items and now it's a really truly reactive property right the read-only card items is a reactive property whatever is changing it our card icon component doesn't care what's changing it all it cares that it is changing and this way you know our component can react to it and compute the new value of how many items there is in the cart and push it into the template what what else we're doing here is in our constructor we're calling the cart service get car products and what that would do is we'll notify the the service that we're interested in that data right so get car products is invoked subscribed the data is pushed it's all reactive great but it does suffer again a few more problems first of all we're getting back to where we do duplicate the network requests so for example uh the general page for you know cart a car content page or car detail page would also need to let the service know that it's interested in that data so we'll also call the get car products so it would be called again and the other problem that we have is say for example we're adding item to the car so we're adding the the editing product and we have a very happy user who was really excited to add many items every time we click the add product it will cause the new http request right so because that's the way it's set up right now right to remember that method it will trigger the method we'll do the post but it could happen that you know the second click the response from the second click arrived before the response from the first click this is network request we're talking here so there's network there's no guarantees of how this thing's happening and how the back-end would process us again no guarantees so we could end up with something that's called a race condition a race condition in this case between cl clicking add products so how can we handle this one well right now the way we are sending those requests we cannot control with the current structure however ngrx for years now has been providing a structure that can really control the flow of data and the order of those network requests which are called effects being the global and direct store or the component store that we'll take a look in a second they both have this effect and they are for controlling race conditions they're also one of those places where you put all your synchronous stuff in and all that stuff but one of the things that it does is controlling the race conditions so let's take a look at the component store component store is a state management library however the state management library is actually just a single file it's a single file of 350 lines of code that has a few other helpful operators but in a nutshell it's still just a single file and being you know state management library it needs to do two things and by the way indirect's component story is completely independent from the rest of the interacts it's self-contained library so it doesn't have any of those dependencies so being a state management library he needs to do three things he needs to be able to read the data he needs to be able to write the data right that it manages and one other thing is control those side effects that we have so we can read the data with the select function we can write with updater uh we can also patch now thanks to marco he added the patch uh of data as well patch state but anyhow these are the main ones and then we can also have the side effects uh with the effects so we can control those all right let's let's take a look of one examples how we can do this let's let's rework our cart service so first of all we'll declare interface and this is the state that this a component store would be working with and in this case it would be car state it would still keep track keep track of our car items uh which would be an array in this case uh then we make the service injectable right and in this case we provide in root but this is not my favorite thing but for this case we'll provide it in root we extend component store to get access to those methods and we'll provide this uh interface there so as a generic so it is aware of what state we're working with then in the constructor we'll inject any dependencies that we need in this case we're injecting a cart state cart cart service but this cart service that we're injecting here is the initial version of it remember that pool base completely stateless one it's just a simple wrap around the gtp calls this is what we're injecting in here and then we need to initialize our component store in this case we'll initialize it right away in a constructor with a super call to provide this initial state however we could also do lazy initialization should we need that okay now so this was now we created it how can we read the data from it well we read it with this select that's provided us by component store and in this select we'll tell it how exactly we want to extract the data or transform it to from our state container so in this case we'll say okay our entire state and we need just need to care about the car items so we need to extract them so we pass that call back we'll say state you know we're extracting the car items out of it and what this uh this select providers is provides us an observable now of those car item array now the next thing we'll need to know from it is the count and we can do it here right away we can provide like read-only car items count and we'll do select but in this case we won't be passing this state we'll be passing the the other observable and whenever that observer limits we'll use this function to reduce this items to a single number right so this is the same function that we're using our this is a pure function right so in this case select can also take an observable or multiple actually right and then it can aggregate those values or single value in this case and and calculate the final uh that file and value that we want from it so car items and car item count are observables they're not selectors nothing like that you can call them selected but they are really just in observables of values and the beauty of select is that not it not only selects it but it also makes sure that it's super performant it has all those distinct until change so it doesn't emit the value if the test they didn't change uh it's very performant because it shares as well right so if there are multiple subscribers for the car item uh observable uh they are sharing the cons so you know each one's not retriggering every of those things it's it's pretty smart and it's very high performance it also a high performance way to accumulate data from multiple observables as well i'm not going to touch on it today but you can go into the docs and read about it it's pretty cool how it does it all right so this is how we read the data now we need to write oh by the way we need to also how will we use it in our component well in our component we can just inject this cart store so this car icon component you can inject the car store just like we do with any other injectable service so it's still a service even though we'll call it a store and it can just read this observable property notice car icon component doesn't have to know that the car store is a store it can just work with it as any other service right so it's just another service it has a property it just subscribes to the properties doesn't mean subscribe it just assigns this property in the class and they will have a sync pipe in the template to unwrap the observable and start listening for those values right great so this is how we read it how would we write it well the way we write it is we have this set card items and we have an updater functions for those what updater does is it takes the state and it takes the value that will be passed to it and then it basically reduces or transforms it or basically returns a new state that we need to settle this uh update and and segar items it might look like a property here but it's actually a callable property so you can think of it as a method and whatever the value that will pass to that method will be passed to the second argument in this callback that we have so in this case car items and you can see there at the bottom where we call this sad car items and we're passing the car items so this updater will then trigger the update and it will update the state with this new value it's really powerful as well and it and it's very very type safe by the way the entire thing is really really type safe type safety is something that i in particular care about and injects as a whole uh was one of those libraries who do have uh very strict typings as well and then by the way we also see this uh this update status we don't we don't have this updater here but i'll show you example again you just take a value and it will uh it could update the state with the value okay so now let's get to the final part the the very exciting part is this side effect so effect we handle them with effects so let's take a look at how this one's so we have this effect method that takes an observable of in this case ids so this is an observable and then we'll tell it how to behave when we get multiple of them so for example his stream right and we start piping these ids and the first thing that we do in this case we'll concat map we'll use this id and in this case we'll call the service to add the product and in this case remember uh our cart service is a completely pool base it just returns we observe it just does the call and all that however we can control all these race conditions and everything that we need for it in this flattening operator concat map in this case what concat map does it's one of those flattening operators we have four of them right and they can help us handle those race conditions so what concat map does is say we've got a new a new value id right and it starts calling the service with this id and say a new one arrives right user keeps adding those products so the new id arrives and what concat map does it says okay i'm busy right now with adding this product id so it cues the new values until it's done with the inner observable when it's done with the inner observable you'll take the next value say what are the other three operators the other three operators would be exhaust map switch map and merge map so concat map queues things up but for example switch map which is quite popular when it when it gets the new value it starts obviously triggers the request when it gets the second value it's what switch map does it cancels the previous request and starts the new one instead right so that operator could cause some bugs during conditions so especially if you are trying to add the products like that probably is not the right operator concat map is definitely the safest one and then we have exhaust map what exhaust map does is it starts the first one right and then the second one arrives and says ah i'm already working on something and it completely drops the second one so it will keep ignoring values until the inner observable is working so obviously adding a product is not this is not what we want as well and final one is the merge map and merge map uh contrary to what concat map does concat map cues them but merge web starts them in parallel right so maybe adding a product is also another idea because the result of the call is what we use and this is the default behavior of the behavior sub uh service with the sub uh subject service with the behavior subject that we had before it was using this merge map strategy by default and the thing is we weren't able to control it any other way this way we can right so we have those flattening operators that we can use so okay we call this uh add product what do we do next we have a result back remember that's an array and the next thing we'll do we'll tap it and we'll say okay when we have the next value we'll call this updater and it will update the state on the error we'll call another updater for example which will update the state to error or something like that and one other important part that we do here is the catch error operator and we'll just push it to void we already handled the error in the tap the the only thing we need to have this catch error and and push it to the uh transform into the uh empty observable is so that our observable stream does not collapse but this you know a very frequent combination that we kept using this tap and cachera tap and kachera they were like basically a blueprint that we pattern that we using more and more and more and more and more so we decided to create a little operator called tap response that basically does those two things it's just a little bit shorter as you can see and what we do you know it would do something on next it would do something on error and the difference here i'm asking you specifically to do something on error because not handling the errors is one of the most frequent causes of mistakes that i've seen so it wants you to do something on next it wants something to do an error and internally will catch the error if if this is the case so tap response available from version 10.1 of the ngrx component store which is uh available already all right great so the top response so how can we use this uh effect how would we actually use this well similar to updater you can treat this add product as a callable property or as a method right so we have we have a product details component that injects the card store and it has this add to cart uh callback probably from the from the from the template and you know see it takes the product id and it would call this car store dot add product and push that id to it so from the consumer perspective from the component itself using this component store it almost looks just like any other service right it's the method that you call but notice what's something interesting we're passing a single product id to it right and we'll take a look at at the top add product works with the observable stream so what happens is quite exciting every time we call this method internally it will push this value into this observable id stream and then we already defined how we handle that observable stream in our component store so that's we wanted to use a cap map and and then we you know set it into our state it's really exciting i think because it kind of brings back that you know calling service methods without any extra things necessary around this there's obviously some benefits and drawbacks of this but there are definitely benefits compared to service with behavior subject all right so now what do we do now well with this card service instead of getting multiple things we'll just have a card store in this case is provided in root and then we'll inject them in both a car icon and car page for different reasons right but this uh right now then each each one can listen to the values and also car page can operate on things right adding things to the to the store and all that call calling those effects and one more time car page is just for example it just calls uh the methods on the card store it doesn't know it's an effect is it an updater it's it's not the concern of the car page all right so this is what we had on the left right this was a service with the behavior subject with all of its drawbacks on the right we have a component store right this is what we're trying to actually achieve and obviously you'll add also like remove product remove all and other things to it as well through those effects so this is how we do so this is how the apis are and the basic idea what it does now where can we use the component store where can we use those are the use cases so we already saw this provided in root there's another use case of complex independent component state and i'll get to each one in details reactive local ui state and finally a shared common component state so let's talk a bit about this provided in root case as you saw right now uh we were we had the components though that was provided in root the card service this is not my favorite approach for sure uh it leads this leads to having multiple services that are prior always available always keeping track of state that nobody sometimes cares about right so they're just there and all that we can do better and also now the state starts to spread a little bit more uh there could be a lot of those common components uh those um uh component stores and that's the idea to have them a lot of them but if they're all in root scope now they're just you know flooding the the thing and then you'll have components injecting multiple those component stores that becomes a little bit more problematic and this is what we wanted to get away from uh when we were creating the interx store for example right so there's a single service kind of thing so provider still has good use cases for example if state is completely self-contained and it's very narrow and it's shared globally it's used in every part of the application for example uh the permission service right familiar permissions user permissions it's it's a very thin state right so it doesn't have a lot of things they could track it's basically a permission list or array of permissions but then it could be used in many parts of the application right so it's very thin it's used all over uh it's very targeted so that one's okay to be in root otherwise if you have too many things that are shared through whole application consider taking a look at the interx store instead all right so what are the other good use case of the component store well this is something we call complex independent component state and let me show you what i mean here so instead of having your card store in the root scope it could be attached basically provided by a specific node that owns the state for all of its children in this case component a could have cart store in its providers and this is in the provider's metadata of the component this is what i mean so we can have providers for the component so component has a provider this card store that means that each instance of product detail component will create a new store for itself but what's what it also means is that cart store now is tied to the life cycle of that particular component that means that when component gets destroyed all the state is cleaned out as well so the card store is destroyed everything's unsubscribed from it's automatically cleaned up this is one of the beauties of the component store now you can have say a is is component a is needed only when one of the pages is opening up when the page opens up then we create a component store we'll do all the requests we'll do all the updates it will share that state should something be happening there and then we navigate somewhere else a is no longer needed we no longer need the state it's destroyed unsubscribed and cleaned up that's a beauty of component scope providers and this is what we call the complex independent component state the other one is reactive local ui state and what i mean by that is say we have a component b and component b could have you know a local state that could be quite complicated has some business logic and all my general recommendation and this is what i try to do for my components is always have components to have as little of business logic as possible so in this case we can basically almost like outsource that logic into the service which is attached to this component and in this case it would be local store for example which is a component store and again it provides the local store and it injects its use it right away so it could be used only within component b it's very localized to this component it will be removed uh once the b is destroyed it could live side by side with the car store there as well so it doesn't they don't interact or they could interact but in general say this is completely encapsulated within the component b but now you have component b very lightweight it basically uses those inputs uh not inputs but it uses the local store and and and calls methods on it it doesn't have a lot of business logic it's very easy to work with and if you had those components that are like thousand lines of code and more you should definitely take a look at this and outsource that logic to this component store all right so and you might also want to break it up into the more components but that's a whole different topic so this is like a reactive local ui and finally the shared common component state and this is the use case that actually i drove so within firebase when i was it was firebase this is what uh basically pushed us to create this component store this was a very common question actually internally and externally as well quite often people were asking hey i have multiple components on the same page i have a presentational component or actually shared or reusable component that has quite a lot of complicated state it has a lot of children as well but then i have say a few of them and they are interact through the inputs and outputs with the container component that has it but i have like multiple of them in the same page you know maybe like three or four this could be a graphs and stuff like that but i really like the reactivity and all that how do i do it all together right and before we only had the direct store so typically was like well you kind of can index each of those components by some kind of index in a global state and then you have all this reactivity but what are you doing is you are pushing something into the global state that has no purpose there it won't be used by anything else it's used only within component itself only for those reactivity and performance so now we have a solution for this component store is a solution each of those components can provide you know when we specify it in providers this common store each instance will get its own store right it will get its own component store so we have it and inject it and moreover if we use those instances or inject those component stores in the children down level they each one get a corresponding correct component store from from above this is how component hierarchy works right so if we inject this component common store in the second level child for example on the left it will go up the component injector hierarchy and find that common component on the left that's providing it and we they'll be reusing the same instance but between those common components they won't be sharing anything because each one have independent state and the way they communicate with the container component is through those inputs and outputs so this is another fantastic use case and this is the last use case that i wanted to talk about how does it compare with the direct store i have like two minutes to talk about this one uh so sometimes in the global store we the difference is that we have actions and why do we have actions actions is a great interaction so we already had one interaction with listening to reactive property and calling methods so we already had indirection we weren't calling the method directly so we had this push-based architecture but now say a component needs a lot of information and needs to trigger a lot of things action provides a second level of indirection it can do multiple things at the same time so for example here custom ratings that we had and if we choose to go with the component store we'll need to get the products and read the ratings we need to let the store know that we need both of those information so basically now our components a little bit more involved which kind of which needs to trigger and it could work fine with two or three uh it doesn't scale well if you go a lot more the beauty with action it can trigger multiple things at the same time so here if we just switch it to you know products opened action that's being dispatched it can now trigger multiple effects each will transform the data and then a selector for example in this case gap product list view model will just aggregate the data and provide it as a view model to the component so with the direct store we are going with a little next level and it pushes the responsibility outside of the component completely and again in some cases is the best way in other cases component stores the other way all of those comparison is and documentation is is at ngrx io so you definitely should check it out all right uh i'm not going to go over the indirect structure i think most of you know what it is uh so we have yeah a store with the reducers and action stream and and dispatching all of those actions i'll skip this for now uh how does it compare well we have those read writes and and effect and jerks has uh corresponding create selector great reducer great effect so those uh both of them do this well but then there are other where the differences are is that in inject store each of those selectors reducers that update the state in effect are basically all separate files so it scales really well right it doesn't matter because as soon as you grow you can just create another file and uh have it there uh well with the injects component store they all live in a single file so the scope of what component store should be responsible for should be really really small right okay and then the other thing with the ngrx global store it's well it's a global it's a single object that has those multiple reducers that each responsible for a corresponding piece of state so they're still responsible for a piece of state but it's still a single object but with the component store there could be multiple of them right they're independent and this is the key they should be independent state they should not be duplicating the state in multiple component stores right there should be one component store that owns that piece of data all right and the other difference is again indirect store is global leads through lifetime of the application component store right could also live through the lifetime of the application if it's provided in root but this is not my favorite use case the real uh you know benefits of component store as well is that it could be tied to the lifetime of the containing component to the life cycle of that all right summary synchronizing state is a very complex task as you can see and hopefully i try to prove it because there's a lot of things that are happening state management libraries have to help to remove this incidental complexity what's incidental complexity this is a complexity that just appears to be woven through your application without you even realizing it right there's race conditions this error handling that's not done at all on most of the cases all of this is this complexity that just happens to be in your application and you have no awareness of it so the state management libraries really help you to remove those and be very specific how do i want to handle those recognitions i have another value right i want you to think about it every time oh okay i'll use one of those four operators this time would be exhaust map right i'm getting get getting product detail if i'm already asking it i don't need another one exhaust map right so i want to be very specific how those are done errors i want you to handle the errors no matter what i want to handle the error if it's just like writing down to do handle the error sometime later you'll have that and you know once you actually run it the production bug you'll you'll come back and you'll have a little bit of oh i should have known better anyhow so stay mentioned libraries help you remove those incidental complexities and and drugs to the rescue we used to have only one global state management and that's where we you know our team is really popular for but now we have a second library complementing it which is really really powerful those two libraries could be used independently you can use one or another or both right because they each have their own problems that they solve really well right so now that adds you another tool into your toolbox that you can choose from and and target the problems and solutions accordingly so a bunch of people uh helped me with this one kevin yelco from firebase team initially came up with the design uh brandon roberts and team uh the driver from ngrx team who uh reviewed all the all the code provided a ton of great feedback on it as well so there was a great interaction but this is my my team uh nicholas jameson also uh provided a great operator for us uh which i haven't touched on he's from the rxgs core team uh and lars as well spent numerous hours with me uh providing great feedback listening me and all this stuff by the way brandon tim nicholas and lars all have blogs so uh team especially tim nicholas and lars are specifically active i do check them out they write fantastic content so interex io guide it's at ngrx.io guide slash component store check out how it compares to the global state the store uh how what the usages are and all the fun part there and the apis uh and finally there are two discourse that i want you to know there's a angular discord which is an official angular discord there's angular team members there there's a lot of angular gdes google developer experts there's a lot of library authors a lot of other cool community members it's international there's some meetup spaces for belgrade as well so do check it out it's pretty cool it's i think it's like over four and a half thousand people there within the last few months that we had it open and finally we also have a discord for ngrx while we have a girax channel in the angular discord this one's dedicated for ngrx so it's split up a little bit deeper or basically for different library so if you want to have a deeper conversations about your ex uh do make sure to join them there's great community help as well uh thank you for having me today i was very excited to present for the first meet up in the angular belgrade uh really big honor uh and uh yeah thank you thank you marco for inviting me so uh i'd like to get some q a as well so if you have time type the question and we'll get to the question yeah here we have uh three questions first is is there any tutorial or guide for using angular fire with component store yeah so from what i hear some exponential discord this is pretty good stuff for firebase it could be um so firebase is itself a reactive thing right but you do you do want to share some of the firebase data sometimes and again this this mix of ngrx and uh and um firebase was always interesting because they kind of do some things commonly right they have this reactive state it's just you just you have to be aware which state of it is goes over the wire to the firebase in general and which states you could still reuse within your application so again remember that persistent state like not all the state goes to the back ends right like which tabs open and all that uh so but then the persistent state could still be reactively populating your uh state containers it could be it could be working with a global store if your data is global and shared it could be working with your campaign component store as well so it could be both yeah hopefully that answers the question let me know if you if it doesn't if there is any tutorial on guide for using the offer angular and i don't have it probably yet i'll be curious if somebody creates a please point at me i'll be exciting to look at it as well okay second question is uh how can component store be used together with ngrx global store yes so the uh thank you for this question inger and manuel by the way for the previous one yeah so they can be used uh how can they how can they be used global store could still have you some of your global data for example in firebase one of the most global data is like for example the project that you're on right so they have like a project id right that yeah the user and then it has so many other functionalities inside but it's almost used for every single request that was sent for the back end for which product specifically you do so somewhere deeper will have a component stores that inject a global store right and then select the product id so we'll have a selector for it and remember how we so again one other thing don't resave it in your component store but you can use it for example in the effect you do the request you'll also use the data like with latest from component of global store right so you'll select that for example global piece of state that you need for the requests and you'd make those requests and you save them in your component store so they could be used pretty much well usually it's not pushing anything not not dispatching anything to the global store but using some of the information from the global store this is probably the most frequent interaction between those two but again they could be used by itself they could be used together they're completely separate and standalone thank you for a question yeah and the last is where's the best place to put the synchronization logic when you need to use multiple components stored in one component so yeah in another service or for sub or in components oh i i see i see somebody who's already playing around with the component stores great i love this question like all questions are great uh eddis this is a very nice question as well so uh the way uh we approached this and uh actually had one of the slides there i just skipped uh so you could my ideal case is you still inject a single component store into the um into the component but that component store can inject higher level component stores into it remember that use case a b where it was a local one so it's fine to create a component store that's just local moreover sometimes it doesn't even have the state typically would but it doesn't necessarily could have a state but it still could be used as reactive facade almost getting data from different other components or combining it together in selectors because again they're super high performance right and again they would be only living for the life cycle of that a particular component right so you could do that i won't i won't recommend injecting multiple component stores into the component i would create i would create a component store that basically is one to one to this component right and in there you'll aggregate the data and do all the fun things should you even call upstream to do something i would alias those things i'll yes those effects i won't recreate specific effects for the upstream components but i will alias the effect and uh and have it all that way hopefully that was somewhat clear if it's not clear enough uh do find me on the discord one or the other uh you can tag me to the question there as well i'll try to get to it once i can get to it but yeah thank you for the question yeah thank you and thank you very much alex for a great presentation we really enjoyed thanks for having me thanks for uh good questions uh love it i wish a lot of success at the angular belgrade and uh thank thanks a lot marco for for starting it uh and and one more time i'd like to call out marco because he's been doing some fantastic contributions to the ngrx monorepo lately i was super excited and happy to see them thank you thank you very much and thanks everyone for coming uh next meetup will be in january we will have two talks first will be about spartacus spartacus's e-commerce angular library and second talk will be about nx monorepo tool and micro front-ends with angular so thank you very much and see you soon bye-bye bye
Info
Channel: Angular Belgrade
Views: 1,503
Rating: undefined out of 5
Keywords: angular belgrade, angular serbia, ngrx, component store
Id: v5WSUE1_YHM
Channel Id: undefined
Length: 62min 36sec (3756 seconds)
Published: Fri Dec 18 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.