Jesse Sanders - Advanced NgRx Techniques | AngularUP 2019 - Full Video

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right so everybody thanks for coming my name is Jessie Sanders founder of rebug and i'm an angular gde and web technologies expert so you can reach me this is my real email address Jesse Sanders at Bri bug comm or you can reach me out on reach me on Twitter at Jessie s underscore Bri bug and happy to answer any questions that you might have all right so in grx who's who's using ng rx right now awesome so in grx do you guys know just had a birthday it's three and a half years old so I think that's that's huge so what's crazy is it has now over eight hundred thousand downloads each and every month so we have a lot of people using a lot of great stuff going on within grx and I'm excited about it I love using ng rx use in projects all the time and we're going to talk about in gr axe some advanced concepts and some things you should be doing and maybe some things you need to stop doing so rules of thumb when ng rx Kate was announced a couple years ago what we started seeing as people would just jump in and start using ng rx on everything from there to to apps to the tour heroes and they're just going a little crazy with use and ng rx so one of the recommendations is to start simple maybe not actually using grx right out of the gate because you probably actually don't even need in grx for a lot of your projects I know that might be a shocker to you but if you use some very simple patterns you can upgrade from let's say something like surface with a subject into inge into in grx when you need it and you don't have to pay the price upfront for it so update later to in grx instead of maybe right out of the box starting to use it that's really good advice you're going to save yourself a lot of time and then really the main concept within grx is we want to reduce complexity and if we start out a project and we're not quite sure if we need in grx we're increasing complexity unnecessarily so so one of the big things that I see people doing right now is they are subscribing to everything ok who's who's a victim of this right yeah yeah you know who you are and who won't raise their hand no matter what I say right exactly I know I know who you are I see you out there yep yeah so stop subscribing that's one of the biggest things that we see is that we're calling services we're working with observables but we're subscribing to everything okay and even worse we do something like this who's done this right where I subscribe and then I do some stuff and returns in newbs everybody scribe to that when it's just change how do you test this you know how you test it you don't this is the this is this is really difficult stuff so if you're writing code like this this is what you need to stop doing and we need to start looking at some real basic patterns on how we can write effective applications using ng rx or similar types of state management I'm going to move this because otherwise it is gonna jingle and you're gonna hear it the entire time all right so who's using container presenter right now or smart components dumb components okay that is look around that's like less than 10% of you so if you are using ng Rx and you're not using container presenter I'm gonna ask that you reconsider okay container presenter is one of the easiest ways you can simplify your components and simplify your in grx implementations as well as be able to implement some of these other patterns like service with a subject and be able to do so very gracefully alright so let's talk about containers really quick so containers interact with the store they're the brains behind the operation and often they're your top level like page or feature level components okay so they interact with the store they pass observable data via the async pipe so the whole thing about stop subscribing async pipe solves this for you who's looked at the code for async pipe anybody a couple of you okay even less people great so if you go look at the code for any seeing pipe all it's doing is its resolving that that observable stream and in unsubscribing for you so you don't have to do it you don't have to worry about memory leaks you don't have to worry about the complexity okay so it's going to receive events from child components so what I mean by this so often what happens is we'll go ahead and write components and I'm sure this is none of you where we write a component and it works great and we want to then use it in another little area so then we just have a little switch statement or an if statement right we just say hey if this variable exists on this session service over here then I want the component to do this otherwise I want it to do that and then you know you come along you add a little bit more you're like oh this is great I'll just have another if-then-else okay cool great and then the next guy comes along and says hey I'm just gonna change this to a switch statement and then we come along and we look at it and this this what beautiful little simple component now has this massive decision tree on how it's supposed to interact right and and so I come along looking at go like wow this is a great component but I'm gonna rip out all this stuff I'm gonna make a copy of it I'm gonna have now two copies of the same component don't do this by doing the Container presenter model here I can actually eliminate that by deferring so the child component will just go ahead and omit events back out and then the parent can decide how they're going to work how that interaction is going to happen that's going to give us more reusable components so containers get to do all the decisions about where the data comes from how it's being loaded what's going to happen when something's clicked on or or whether it be a system event or a user event how we are we going to do things so here is an example of a dashboard component that is a container so you can see here I've got a hero's variable it's of an observable stream of hero array I've got my hero service coming in and I've got on my ng on an it I am setting my hero observable equal to the hero service get top heroes okay notice there's no subscribing I'm not trying to resolve this I'm gonna allow it to be an observable stream if that stream gets updated my container is automatically going to have that updated data and there's going to pass it automatically down to the child via the async pipe and here I've got an event handler on here Oh clicked where it's going to receive the hero and we're gonna go ahead and navigate or whatever decision that we're gonna do with this hero so our HTML here is very very simple this is where we're gonna wire up our our child component what we're gonna call our presentation component and here you can see that we're passing down heroes using our square bracket notation and we're unwrapping it using the async pipe again no subscriptions nice and clean it's gonna go down to that child component is just native hero array data right and on the on hero clicked event we're going to have that be handled by our function or I'm sorry the hero clicked event will be handled out by our own hero clicked local function okay that's the basic premise of a container very very simple so talk about presenters what our presenters therefore really presenters are also what are known as the dumb components they're there to just really honestly make things look pretty they don't understand where data comes from it just sorta kind of comes from the sky and they receive it and they go oh they thank you I've got hero data that's fantastic let me make it beautiful when somebody clicks on a hero or does some sort of interaction it doesn't actually decide anything there's no decision trees inside of our presentation components about what to do it's gonna just kindly take that and say hey somebody clicked on a hero I don't know if anybody's listening but I'm gonna go ahead and annum it's an event back out and whoever's listening here's the hero that was clicked do whatever you want with that so presenters are very very simple what happens here is by doing this we're now creating highly reusable components that are very very easy to test that have no logic in them and we're doing this basic concept of defer defer defer so here I've got my top heroes list component I've got my input I'm receiving heroes as hero array again no observable stream there's no I don't have to unwrap anything subscribe to anything it's nice and simple i muscled declaring an event emitter here so that I can go ahead and raise events back out and I've got on my hero click I'm going to go ahead and mint that emit that data out and you just see if I can make this a little bigger here there we go that way I don't have to keep looking back over my shoulder excellent all right so that's our our presentation component so the next thing I want to talk to you about is service with a subject so often I hear people say hey ng Rx is really complicated I don't really want to write a bunch of actions and reducers and effects and I do I kind of want some state management but I don't know what to do so they ended up taking shortcuts and they do really bad things instead of doing a good pattern so one of the patterns I want to talk about today is service with a subject anybody doing service with a subject now currently ok not not very many if we look around a few hands up alright some people aren't going to raise their hands right that won't get over there he's not going to reuse hand no matter what all right so service with a subject is a very simple concept here I've got a user service that I've defined and I go ahead and create a private member variable called M user dollar sign and it is a is a behavior subject anybody know why we're using a behavior subject versus a regular subject okay yep got a lot of great answers being tossed out there the and and I and I definitely heard I think you said over here the difference between a a regular subject and behavior subject is with a subject if I show up to the party late the party's over there's no data I don't I don't actually get the value with a behavior subject it'll go ahead and hold on to whatever the last value was so it doesn't matter when I show up to the party the party is still raging we're good to go we're rockin and rollin right I've got some data so my case here with my behavior subject I'm gonna go ahead and initialize it I'm saying it's of type user array and then I'm initializing it to an empty array so that first value that that someone's going to get is going to be an empty array and I then create a get a property getter here just called user dollar sign that returns an observable user array and the key here is I want to go ahead and then take our behavior subject and return it as observable and this prevents people from doing some crazy silly stuff where they might decide hey I've got a I've got the behavior subject I'll go ahead and next another value and modify the stream we don't want that to happen so we'll use something like as observable this is not required this is a preference I think it's a good idea depends on what type of developers you're working with and what types of systems you're trying to create so our case here now we've got our load all method instead of load all returning this client HTTP client get now it just makes the call and with our HTTP client call we're calling yet we're expecting a user array and we're calling API users and then we're subscribing to this now before anybody like jumps up and says hey you said don't subscribe right well this is the one exception here I can go ahead and do a subscribe and because it's the HTTP client call it actually auto destroys this and unsubscribes to this and so I don't have to worry about managing that in this case here I want to go ahead and subscribe to it so that I can get the data that was returned and I can go ahead and add that - my behavior subject stream so who's heard that that's that's in a nutshell that's that's what what service with a subject so let's talk about if you are going to do in grx who's heard about actions right everyone knows about actions and did anybody remember Mike and Brandon up on stage during one of their talks and it was like you know actions are the the glueten of the in grx loaf or one of my favorites here is that it's the mattress of the the in grx bed so actions are the critical aspect here and it's something that we see a lot of people start to take shortcuts in it's a really bad thing to do no shortcuts if you're going to take shortcuts I'm going to recommend some other libraries to you some ways that you don't have to worry about actions as much you can take advantage of the library and not do something like this where we have a single action that does everything anybody do this nobody should be raising their hand hopefully but where they have a single action let's say called update users and we have our reducers do all sorts of stuff for manipulating data using our lovely subscriptions and we're making changes and morphing our data and then we just have this single action that says hey now go ahead and update the users with this this is a real world example actually from a client that we looked at they couldn't understand why they weren't able to to really get in grx to work and work well and be able to track what was going on and once we started breaking it down it's like well how are you expecting to track it you've only have one action so you really need to start thinking about actions as really being a three-part deal here so three interactions one is hey I'm making the request go load users and then I've got two additional ones and this is what I'm describing here is a basic crud operation for you so go load users and then we have either load users success or load users error okay so we have three different states that we're trying to manage and the load users I'm actually going to then say hey clear out any existing users that we already have from the store go ahead and set loading to true and set errors to nothing when they come in the data comes back then then I'll go ahead and set loading false and I'll add the users to the store and if an error occurs I'm going to go ahead and set the error right so don't take shortcuts you're actually going to find that it's gonna cost you more time and more effort to debug and figure out what's wrong with your application when you decide to not be verbose in your actions so selectors who's actively using selectors heavily now okay who doesn't use selectors at all nobody no one's gonna raise their hand to that one okay so selectors are really where the power are power is within in grx so with selectors once we have the data in the store now we can create new slices of state using selectors why are these so powerful one is because they're composable and the other one is because they're memorized so composable means that I don't have to write one big selector routine to get my data mapped out the way that I want I can actually chain them together one selector after another creating various inputs and and then be able to get my data into a format that I want and in memo I says hey that's great once I have a calculated value and as long as the store hasn't changed when you ask for getting the total of something it's automatically going to bring it back to you we don't have to recalculate it at all so we're getting some caching there so selectors are great for doing any sort of mapping sorting filtering anything that you need to do within your application once you have that the data into your store then then you can do some manipulation now when I see that I don't mean go load your entire database put it into your store and then use selectors to do that it's not a good pattern it's a very bad anti-pattern so one thing that people often don't know about is if I have a selector called select total and it returns a memo a value of eight and let's say select total is actually depending on both an order store and a product store and something changed in products but the order store didn't change at all in the selectors actually based on orders then every every time they asked for select total it's still giving me eight even though it should be nine or ten or whatever that new calculated value is and so something that a lot of developers we see struggle with is they don't know about this thing called release so if you're having an issue with selectors and you're you're in the case where you're getting a memo i's value and you don't know why it's not changing even though a related store has changed you're gonna need to manually call the release on that that's something good to have happen oftentimes in let's say like an effect so that when you make this call you make this change then you want to go ahead and release that selector so it's no longer available so all right nested data who's had to deal with nested data within grx or within their applications so this is one of the it doesn't seem like a really bad thing to deal with but it actually creates a lot of problems a lot of complexity so one it's a bad practice so when we have nested data what we often have is duplicated data there's actually a talk by the way this is my second time here at angular up and this is one of the things I talked about last year was nested data within grx entity and so what happens is for us to be able to update this data we have really bad reducers and what I mean by bad reducers instead of having a single one or two line sort of reducer that's really easy to test and understand I have this really big mess of a reducer and what happens is that it's really easy to mutate that data and we mute that movie if we're not using something like the the store freeze we may not realize this till much later often usually in production in a really bad situation right so we want to go ahead and break data up so in this case here I've got what would be a blog article and I've got a couple blogs to find here and it's got an author attached to it and then I've got my title and I've got some comments so I've got really two different types of authors or users of the system I've got Jane and Bob here and they're both have written a blog article and in both of them I've made a comment and you can start to see here that we've got some duplicated data okay now if Bob actually now decides he wants to go by Robert now we got to go find all the different places that we have Bob stored in our store to get that updated okay not a real good practice also if I try to just update Bob's comment down here I can't just change the comment out the entire object is is going to have to we're gonna have to have a new instance of that otherwise we're going to mutate it and and also an unexpected of that is now any any components if we have a large nested component structure then all those components are going to have to re-render as well so we start to run into some performance issues there so what I would suggest to you is prefer to go ahead and break these apart so now I've got blogs and I've got users and I can go ahead and make references to those so works pretty nice this in itself actually still you're gonna run into some problems and so the one of the next things that we're gonna talk about is in grx entity and why that'll actually help you solve this problem so with nested data we want to go ahead and split nested data apart for the store so you can do this in the service itself on the SUBSCRIBE you could do this in your effects you could do this in helper functions any one of those three it's fine it doesn't really matter where you do it at do what's going to work best for you and and making sure that you're you're not repeating yourself so dry concept there and when then when we go to actually put the data back into our components we want to then reassemble the data using selectors so this often means then we need to create a new model that actually reflects the data together so that we don't have to pass down separated data and and and having to do a bunch of different selectors that we'd actually want to have a selector that would pull the data out put it into a new view model that we could pass directly to a component alright so this leads me into ng rx entities so injure rx entity anybody a ninja rx entity currently Wow not a lot of hands this is probably the number one library that I would suggest that you start to take a look at in terms of if you are going to use ng rx you should be using or at least considering ng rx entity now if your if your data is very very simple we're not dealing with array based data with IDs like you know we're just doing some to-do lists or we're doing just let's say UI configuration sort of data where we're not having to deal with that then you don't need to use in grx entity but in grx entity if you're loading data from an API and you're dealing with arrays of objects then in grx entity is going to save you a lot of time in a lot of headaches and it's going to allow you to do this relational data on the client side with very very little work on yours so within Gerak's entity it prefers dictionaries over arrays the faster are super fast because or that the finds are super fast because it can find the data by the ID and I don't have to go you know do some sort of index filtering looking over the entire array trying to find a product ID that you know has one two three four the ID it's got built-in methods for how you take array based data and make a dictionary based data and it also comes with selectors that allow you to take it from dictionary based data and put it back to array based data so that you can use ng4 and and other directives like that what's interesting about this is I was looking at the stats last night so we've got 800,000 downloads of in grx a month but we only have approximately three hundred twenty-two thousand downloads of ng RX entity so this tells me that we have a lot of people that are not using this and you really should be okay save yourself a lot of time a lot of headaches so let's take a look at how that data is stored so here we've got blogs and it has two properties on blogs notice there's no array here so I've got blogs I've got entities within that and I've got IDs so we'll start with IDs IDs is actually the list of IDs in the natural order that they came in so when we go to use our selector it's going to enumerate over the IDS and say hey give me the one that's got an idea of one give me the one that has an ID of two and it's going to recreate our data in the same exact order this isn't as big of a deal if we're wanting to just sort by no more numeric ID order but if we're doing something that's more using grids or something similar or different sort order we need to maintain this so that's that's where that comes in handy and so you can see here we have key value pairs our key is our ID and our value is our actual object here so this is our blog object now notice I have an author ID of one so now using my selectors I'd be able to get a list of users it's gonna have a structure very similar this and I can say hey give me the user square brackets 1 boom I've got the exact user I need I don't have to enumerate over anything so let's say you don't want to actually do in grx fully and in grx entities might be still a little bit too much work for you then one of the things I'd strongly suggest to you is take a look at in grx data so this is an implementation built by John Papa and Ward Bell was announced about a year and a half ago at ng-conf so I guess a little over a year ago at ng-conf so this allows us to do a simple configuration to declare what our entities are and it's going to do all the heavy lifting for us so it's built upon ng rx entity the the data is actually going to store itself in the same using ng rx entity underneath the covers but all you're gonna have to do is interact directly with is as a service from your component and you're not going to have to know anything about actions reducers effects none of that it's it's automatically going to happen for you so I like to call this this is kind of like in G easy in gr X okay you don't have to do a lot of work and then when you're ready to upgrade or you want to kind of eject out of this it's very simple to do so all of its over writable and and there's great documentation out listed in the readme so what does it look like so here i've got a hero component if i want to go ahead and do an ad i just call my hero service ad and the hero that's going to go ahead and place that into the store same with the lead it's gonna remove it I can now make calls to go get data and that's going to put data directly into the store so then I can go get that data back out later so it's really simple interactions using services that are that are also in large part they're gonna extend an existing service and most of this codes going to be really neat underneath the covers for you and you're not going to have to know how to work how to use it so this is a great way to start projects up and get things going very very quickly so next thing I want to talk to you about is in grx schematics so index has its own schematics the other one if brie bug the company that I own we created some schematics called in grx entity schematics and this is going to generate out a whole bunch of code for you that includes your model your effects with tests your reducer with test a service a bunch of selectors so it's going to do basically everything that you need for crud operations and you're not going to have to write a lot of code so if you want to be a little bit more explicit and have actions and be able to modify this stuff this is a great route to go if you want to be a little bit more implicit in your X data is a great way to go we also have another thing that we've been working on experimental we've been working on this with a several projects and it's called ng rx auto entity and this actually allows you to use generics where you could say hey I want to do a load by ID and using my angle bracket say I want to load customers and it has a whole set of crud operations available to you it's kind of a an in-between between doing ng rx data and doing schematics and being very explicit and something for you to check out if you're interested all right here so let's let's move on to ng rx facades anybody using facades currently in their applications so good friend of mine Thomas Burleson wrote a great article on facades that I highly recommend for you to check out it's very similar to service with a subject basically the idea is that we can remove our ng rx implementation out of our components and move it into the service this also by using facades when I move from service with a subject to ng rx by using facades actually my components don't have to change at all my components can stay exactly the same so this is your upgrade path so if you're thinking hey how do I go to 2 in grx without paying the price up front this is exactly the roadmap for it so it hides out in grx implementation so here I have a facade called the user service you can see I've got a function or a property getter here where I'm getting my observable but instead of pointing to a behavior subject I'm using my store and I'm using a selector to get all users and then you see I'm injecting the store here my second slide that's related to this is now my load all function instead of it making a direct call to my HTTP client to go load the data it's just going to dispatch a new event to say hey load all users and the effect is going to go ahead and pick that up okay so in grx façades are gonna save you a lot of time especially when you're deciding between service with a subject and then moving up into ng rx which by the way you can have applications that are intermingled with both use ng rx on your most complicated pages first the ones that you're you're trying to manage complexity and you're trying to deal with really tough timing issues in TRX is perfect for those you can go and upgrade those two in grx and then just update your facades your service with a subject to this facade pattern and you're done your components don't have to change at all most importantly what I want you to here is I want you to find a tool that works for you so some people are gonna say hey don't use enjoy X data don't use this don't use that don't worry about that don't take shortcuts find the best tool that works for you and your team and and and be as efficient as you can in building your applications make sure you've got a clear line of sight to your upgrade path so that things are gonna work well for you so we got a couple we're gonna run a minute or two over here so we're gonna hurry for in grx testing Jess jeaious is the my preferred library for doing this it's super fast I get to run failed test first and snapshot testing is the way to go so here I've got a test that is testing a my reducer I've got my expectation there where I'm calling my user reducer I'm given an initial state I'm passing it my action and I expect it to match my snapshot so no longer do I have to manage what the expectation looks like and having to create object literals manually now I can actually just say hey compare it to the snapshot that was before to what it is now if there's a change then then alert me and tell me I've got a problem and then I'm gonna manually go visually inspect those and figure out what's going on is this correct based off the changes that I've done and these become part of my get check-in and become part of my get flow and the PR process so this is perfect for testing reducer selectors effects I can tell you with when you're testing effects you're going to want to bring in Jasmine marbles we don't have time to cover this we're running a little long here but Jasmine marbles allows me to go ahead and control asynchronous operations in a very synchronous way by the way I'll make all these slides available and I'll post them on my Twitter account so you can have all these slides when we're done on also with testing if you haven't checked out Cyprus I oh it's one of my favorite products to use lately it replaces it replaces protractor it makes end in simple they're much more reliable easy to test edge cases and they're fast it allows us to stub out the data that's being returned by our API calls it's unbelievable it's a bit of a paradigm shift but you're gonna go from having flaky unreliable tests a test that you can absolutely stake your life to that that they work and you don't have have to worry about it all right last piece here I want to talk about we're talking about actions what I want to dig into here is that you've got really three types of actions command documents and events we think about actions here I've got an example of an effect and the the command is hey I want to insert a user the document part of this is hey we have a user go ahead and insert this into the store and then I have an event that's handling a user error so I want you to start thinking about when you're creating actions what type are they another aspect I want you to think about is different types of effects so we're gonna cover the first three very quickly here we have decider splitters and aggregators I think aggregators are probably the most exciting here I've got a in effect where it's getting with latest from and I'm getting data back from the store and if user ID is this then I can do that I can dispatch this action or if the user ID is is less than 0 or equal to 0 then I can do this action instead it allows me to do some decision tree inside of my effects and I can have one one one action here end up triggering another action instead so splitters are very interesting this allows me to say hey look I want to have a single action here and when that happens I want it to kick off a series of actions so I might use something like a flat map and say when we want to load the admin user I want to call a load user by ID and I want to do a log operation so we want a log who this user is it's requesting admin access okay this allows me to split it off these can now each have their own effects that are handling these and and have their own outcomes on on success or failure and the last one here is the aggregator which in this case if when we call load by our action of load user by ID now I want to watch and make sure that I've got that my success handled and my logged handled those would be my success actions from each one of those from the prior slide and when those happen I want to dispatch a new action called load admin user success so what's fascinating here is if I have a series of actions that I want to wait for for them to complete before I kick off the nest next action aggregators are a great way to do it and with that I created a bitly link here called AG ops because you could use I use zip in my example but depending on how you want it to interact you can use fork/join zip combined latest or with latest from and get different ways of how that data is being handled based on when the observables are firing last piece if you haven't heard of log rocket go out and check it out it allows you to record sessions it works great within grx because allows you to use a meta reducer to track what's going on with your users it's free up to a thousand sessions a month you can recreate all bugs even ones that aren't reported you have all the data that they've been receiving you actually get screenshots of a little video of what was occurring so you can no longer say the bad part is is you can no longer say it works on my machine ok you can actually recreate their error if you go out to log rocket comm you can learn more about it highly recommend it really cool product with that thank you so much great being here back in Tel Aviv [Applause]
Info
Channel: AngularUP
Views: 1,995
Rating: undefined out of 5
Keywords:
Id: YbYj4b2yIN8
Channel Id: undefined
Length: 35min 25sec (2125 seconds)
Published: Sat May 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.