NgRx Selectors How to stop worrying about your Store structure - David East & Todd Motto

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everyone thank you all so much for coming out this talk is ngrick selectors or how do not worry about your store structure yes so hello I am Todd motto I came all the way from England to be here today and I said I'm David East and I came all the way from Denver one hour flight it's a big trip so despite the the distance between David and I we've been friends for quite a while and we were learning in grx a few years ago together we jumped on Google Hangouts we were talking about things and actually have a picture of David and I yeah so this is Dave and I learned in in grx so we weren't really too sure what we were doing and we're here today to present a few things that we overcame and the funny thing was is actually during this time that time I met I was working on an ng rx app that was in production and I was like a really big like champion for using in Jurek so I went up to my manager and I told her I was like we need to use ng rx like we have all these state changes and like injured synchronizes state change is going to solve all of our problems and the funny thing was is this was actually kind of my first engineer except so rather than using it to solve all these problems I kind of created a lot of problems and so today we're going to show you a lot of the problems that we ran into and what we used to solve them so one of the biggest things is the store and it seems really simple at first it's this magical object in which I can subscribe from and then I can get state state changes when they update and render it to my view and it's all kind of simple but the big question is how do i structure this store for an entire application so you might have a component and it renders a list of current orders so the obvious thing you could think is like okay well I'll just take this list of current orders and I'll make that a custom slice in the store but then let's say you have another component and this component is responsible for rendering past orders so you're like all right I guess I'll take that component state and I'll store that in my store as well but then I needed to store all orders and this is where it got kind of weird for me because I was like well if I have current orders and past orders that's all orders I don't really know I was doing so I was like I'll just store all the orders as a third slice in the store and at first the reducer for this was actually kind of easy it kind of tricked me into following this pattern and so I would switch on the order load success and that pretty much would give me some actions over the network and I would take this array and I would just start filtering it so I would get my current orders by just filtering on the is active property and to get my past orders I would just invert that and then I just tack on all my orders and I thought this was really easy but then I had to update this data yeah and this isn't the easiest piece so this is nice and clean or the load success we end up with three lines of code and it's it's a nice space but when we want to start updating things we also can create things we can delete things so what does it look like when we want to update we could do something like this which isn't you may know may not be able to be able to see it it's so small but it takes a lot of cake we've got too many loops we've got all orders for past orders we have to manually iterate through everything we have to detect something that we're trying to change and then rebind it to the state tree now this is just one reducer so if you imagine you've got 100 reducers 200 reducers this is going to spiral out of control so you may look at your codebase like I have many times and you come back to your reducer and you think what is happening who even wrote this so at this point I was kind of like maybe we're missing something what do we miss so we went back to the drawing board and we checked out this diagram the lovely diagram that took me ages to do so we looked at the diagram and we my expectation was I can just dispatch something put it in my store and then I get this new state back but if the problem with this diagram is if you only use these three tools your actions your reducer and your date you're going to run into the same problems that we ran into and so time I got to thinking and we realized that we had to redo this diagram that we needed to rethink and we actually I think Todd stayed up all last night doing this diagram so you show us some time yeah big change so selectively really are the missing piece with selectors we solve all the problems that we ran into before and you might have seen selectors on a tutorial or video or in documentation probably not in documentation but you know you might have seen it somewhere and you was communicating to is hey this is an advanced concept or an intermediate concept you don't need to learn this at first but Tom and I are here to say that we think that selectors are a fundamental concept of ng rx that they are there's not just three circles than GX there's four and selectors are really really simple so you it's easy to learn them at first because they're just queries to your store and selectors provide us with a lot of great benefits yeah and the few things that we should ideally look for with these benefits we get a nice API for composing our view models we can reduce our action boilerplate which is a hot topic at the moment and we can simplify our reducers and we also have memorization thinkit's should be spelt with an S and we also have the routing state as well so the route and state will come on through this is my favorite piece we saved it for the end so it's actually really easy to refactor your store for selectors as well so before we have these three slices of state and we were filtering out and you know this is a lot to keep track of we don't want to do this so it's just delete them and instead of keeping track of three pieces of state I'm going to keep track of one and like before when we had to update state I want to do a order added action it's really simple all I have to do is like add a new order I'm updating one piece of State now three pieces yes so we've kind of reflected the the producer and we've taken those three slices of stay out now we treated those as more of a view model so how do we actually get the view model this is where we introduce create feature selector and its sibling create selector so these are two things that we need to create selectors where we can go and compose those view models so these posts come from ngrick store package you can import both of these and we can say that we want to create a new reference to this new slice of single slice of state that we have so we're gonna say give me a feature selector and we're just going to pass in a string value give me that property of orders now the difference between the two is the create feature selector we have feature modules in angular so we have an app module we might have a lousy lazy loaded orders module so the feature selector is for feature modules it will dynamically bind itself to the state tree so this is how we can create a reference to it so once we've got that we now want to come out of the reducer we don't want to do any view model stuff in there we want to compose it here so we're gonna say that we want to get the current orders so this is how we're going to learn how to compose it and we could just pass that first selector in as the first argument we then get a function argument we get the orders given back to us so this function will get executed and we can then map over things we can filter them and we can just return the active items so this solves that one problem where we have all the current orders now this functions got a projector function and we'll come on to some more complex uses as we continue as well so we also have the passed orders so how do we get the passed orders we can simply like we were doing inside of the reducer we can just invert that expression so this is nice and clean and it's nice and simple and using the selector is really easy to do all you do is inject the inject store into your component and then what you can do is just use the Select method then just pass in your selector just like that as you would usually use with the Select API and so before we had three view models sitting in our store and we switch that to how three selectors and the really big benefit of these three selectors is that they are reactive and that's just kind of like a really fancy way of saying like I have one component here my current orders component it's going to dispatch that a new current item was added and what that will do is it'll recompute my selectors for any query it matches so since it's a new item it'll recompute my selector for getting current orders as well as getting all orders and then as you can see it did not update for getting past orders because it wasn't affected by it and what's really magical about this is that it's just one update to synchronize multiple pieces of state rather than managing multiple actions and trying to keep everything in sync in your store so the issue that we looked at the beginning was having these initial three arrows where we had three slices of state and expanding scaling the store becomes quite challenging so let's assume that we've got a new requirement and we for practical reasons want to click on an order so we want to go and get that order by its ID now there's multiple ways that we can do this but let's look at how we could do this with a selector so this is a slightly different one because we are as you can see we have a parameter we have an ID so we're expecting to be able to pass something into it and get something back now if we take our initial selector so a good thing to remember here is that we can reuse these selectors we can compose them in multiple places so we can pass in all of our orders which gives us this back we can then say I want to use the array prototype fine method and we're just going to try and iterate our collection and find that single ID so this is nice and simple it works but there's kind of an issue with this what if we want to render say 10,000 items wait why would you need to render 10,000 items my project manager told me so rather than having to loop through a thousand item just to retrieve one we would rather just be able to quickly access one item and that is something you can do with the NAD pattern and you may have seen in some talks today the ng RX and ad library and we're not going to dive specifically into that library but we are going to show you works underneath the hood and how you can actually implement it without using the library yes so this is a really cool piece and if you're starting with ng rx then this is a really nice thing to kind of dive into from the get-go so let's assume we've got three here but we could assume ten thousand so we've got an array and now we've indicated that an array we have to loop over things we have to filter we have to map and it becomes a challenge just to update something we have to iterate and replace so the proposition with an entity pattern is we have these three IDs we've got 1 2 & 3 now what if we flatten these to an object structure so we take those unique IDs which ideally would be generated on the server and then we say object 1 give us the order 1 and so forth now the benefit with this is we've mentioned arrays are kind of bad we have to iterate and if we did have 10,000 items then doing something like this would not be possible we've we have entities square bracket 3 and instantly it gives me that one back one back so we have number three and we could pass in number 10,000 if we wanted to and if we get it back as fast as number three and using the NAD pattern in a reducer is actually really easy because it standardizes how we can write it so right here we get our orders back as an array and we don't want this to be an array we want this to be an object so this is just like an imaginary flattened method that goes through and turns it into an object and so now that we have it as entities we just put it as a property on our state tree however we've kind of built our application we're using ng fours and changing everything over to an entity pattern immediately breaks everything so why does it break everything don't worry there's a simple fix using selectors ironically so we can use I'll get all of that our order slice now this is no longer an array it looks like this so we're actually having orders and we want to return that dot entities so we're just creating one reference to it then we can say okay because my application is broken my ng fours aren't working how do we transform these entities back into in a ray for a view model now we learned that we don't put view models back in the reducer so this is where we can then compose these so we can just say object keys which will give us basically our previous example where we had 1 2 & 3 then we iterate those and we return each entity so we get a brand new array from this now the benefit is this is just one data structure and we're using two selectors we've got our data in one format object forms and we've also got an array form I've said this there we go so like Todd said the NAD pattern is really good for fast object lookups if I look at something trying to get something but 10,000 item in the list it's just as fast as getting the first item in the list and it really simplifies the reducers because it gives us a standard way that we can write them and we don't have to worry if we're doing it the wrong way but where the entity pattern really shines is when you use it with the router so with our get order by ID selector we need an ID to get an order so it makes sense that if we took a router path of / order / 1 well that one is the obvious candidate to pass into this ID so you might be thinking like okay I guess imagine how we'd do this so if we have a component we we have this order detail component and so the first thing I'll do is I'll go to my router and I'll get my router state and so this order ID is the router state the slush orders / 1 so since I have this ID I can just select this and put that ID into the selector now this is really easy but there is a problem with doing this and that's because I don't want any routing code in my components like routing code belongs in route guards or resolvers but the great thing about ng RX is is that you can actually use routing code with selectors and this is where the this is probably my favorite piece the route to store package comes into play now you can download this as well it's available on NPM and you can get it up and running probably 20 20 minutes now the benefits of doing this is one we remove our routing from the component but we end up with treating the whole application not just the angular logic but things like the URL bar as this single state tree so we end up with something like this where we have the root of reducer and this is given to us for free and we also have this state property now you can populate this state property with anything that is available on the activated route snapshot so let's assume that we have the URL of orders and we also have this params of one so we can have slash orders slash one and this is just immediately available in the state tree so taking our get order by ID example how does this actually benefit us so let's create a new feature selector this will be probably in an app module in the root module we can create a feature selector that reference to this route to reducer now again this is given to us by the NJ rx package the route of store package now this is probably the mind-blowing bit it was for me at least so let's take our entities so our object structure which is made up of keys of 1 & 2 & 3 and we've got that paramah well so secondly we can then say give me the give me the entities and give me the Rueter state which in our projector function gives them to us in the order that we passed them in so we have our entities and the router which the magic the recipe here is that we can look up that single entity with there's no loop it's super fast and we get that order ID that's available to us on the params so we can add it in there instantly now this when we navigate away come back and go to a new component in the background the route restore package is keeping all of this in sync so you write this code once and it's there you don't have to touch it again and using this in a component we can go back in refactor it so we don't need the order ID anymore and we're not calling this selector as a function because it's automatically being handled for us and what this means is is that we don't have any routing code in this component so there's a new recipe for being able to not worry about your store structure so you want to follow the entity pattern embrace selectors you want to avoid view models in your store and like we just seen using them all together with the routes of state really improves the state tree and your selectors so when you're thinking about how do i structure my store well it's not how do you structure it it's how we ask for it so the next time you start an engineer X app or you have to go back and refactor a reducer don't worry about your store structure just think selectors first thank you thank you very much [Applause]
Info
Channel: ng-conf
Views: 35,321
Rating: 4.9154558 out of 5
Keywords:
Id: Y4McLi9scfc
Channel Id: undefined
Length: 18min 33sec (1113 seconds)
Published: Fri Apr 20 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.