Transcript from the "Redux & NgRx Overview" Lesson
>> Lukas Ruebbelke: All right, so Redux, I would say, falls into kind of three primary concepts. So the first one is that your entire state is in a single state tree. Secondly, is that state flows down from that tree into your application. Thirdly, is that events are captured and dispatched the action objects into a reducer.
[00:00:30] So the reducer is the only place where you can mutate application state. Now, fundamental precept of this, is that the methods inside of a reducer are performing a mutable operations. And so, in another words, it's not mutating state, but it's making a calculation in returning new state. And so, this has some significant performance advantages.
[00:00:57] So one, when you have a new object, the memory pointer changes. And so, immediately you know, this is a new thing, just update. Instead of with AngularJS, one of the big problems is, is that they were doing like a deep comparison of like, this property change on this object, but we don't know what.
[00:01:20] Or even worse is, did it change at all, like, and it would go through and examine all of the properties on that object. And depending on the object and how many you had on the stage, that got very, very expensive. And so, instead of doing this deep comparison of like, hey, what changed?
[00:01:39] It's easier to say, I know this thing has changed, we're just gonna swap it out. Secondly, is that it allows for an atomic transaction within your application. So for instance, as we saw, or imagine if you're binding to an object that's bound to a form and I start typing in the form, well, what's gonna happen?
[00:01:57] That object is gonna change. Well, how do you undo that? I mean, it's very, very hard to do, like you have to, I mean, in some cases, you simply cannot refresh the page and hope that nobody saved the database. Whereas, if your working on a piece of state and your like, I don't want this, you can just throw it back, throw it away and go to the next piece of state, or the previous piece of state.
[00:02:22] So with these transactional, with these atomic transactions in your application, you can move forward and you can backwards, and so we'll see this when we pop out the dev tools, and we can start to see these applications or these actions, or these slices of state go through our application.
[00:02:40] So think of the store as your database in your application. So the entire, all your state is in the database. Now, think of reducers as tables. And so, just as I would organize a database in appropriate relations. I've got projects and users, and so, kind of by distinct entities, you would generally want to create your reducers to kind of map to those distinct entities.
[00:03:11] So think of it as a very normalized kind of a structure. And the store itself, we can think of that as just read only, but if we want to mutate the state, then it happens at the reducer. And how we communicate with a reducer is via an action.
[00:03:32] So we query the database via selectors, and so we can say, hey store, give me this data, and I want this slice of state. You can display it. And then, something needs to update that, then you capture that, that update into a payload, and then you say, okay, we need to do this action, action type, and here is the payload, you need to complete it.
[00:04:01] It goes into the reducer, some calculation is performed, and so in other words, it's reducing everything into new state, and it goes back into the store. Now, the beauty of this, because this is built on top of observables, that when you have an observable stream and you change something in the stream, is that it's automatically pushed out to the consumers.
[00:04:29] And so, if you're updating state over and over, and over, so you know, let's say, we have new users coming in, that any time that state changes, is that observable is triggering a next event. And then, going and pushing new data to your components or your services, or whatever is consuming this.
[00:04:48] So this is a very efficient way to propagate new state changes through your application. So I mentioned this yesterday, but if I was going to talk to a brand new Angular developer about Redux and NGRX, where I would start is component-driven architecture with inputs and outputs. If you have a parent component and you wanna pass the data or state into that child component, how do you do that with an input?
[00:05:22] And then, anytime that state changes on the parent component, it updates the child component. So the child component is not having to worry about where the state is coming from or how it's being manipulated. You just know is that, hey, when I get the state, I'm going to display it, I'm going to bind it to my template, it's going to happen.
[00:05:39] So state flows down from a parent to a child via input, which is because you're using Angular binding, when it changes in one place, it changes in the other. And if something happens on the child component that you need to communicate back up, you do that via an event.
[00:05:58] So you understand that when something happens, the child component is now responsible for handling that. It goes to the parent component, and then the parent component can do what ever it needs to. And so now, you have these pieces or these parts in your code, we're simply saying, go and you give me the data, and if something happens, I'm going to let you know.
[00:06:20] So state flows down, and anytime state changes, you're gonna get those changes that are going to flow right down to you, and you're going to react to them. So we're here, reactive Angular. And then, when something happens, we're delegating it back up. And so, that is the basic shape.
[00:06:37] Imagine all your state in a single place, state flows down just like parents or child with an input. When something happens, events flow up into the reducer, just like if you had a child component dispatching an event, it's that same exact concept. Now, there's two caveats to that that I'll get to in a little bit, I'll just leave a hint, is what happens if you need to communicate to a server or do some asynchronous action, this is where effects come in.
[00:07:07] So this is really key for handling control flow, of like, I need to do this, this, and this, in this order. Having this in a single place that is wrapped in an observable sequence is phenomenal. So we need to do asynchronous things, those go in effects. And the other piece where it's like, okay, that makes sense.
[00:07:28] Now what happens if, for instance, you have users and widgets, or related entities? How do you get those back together? Because if they're separated, what do you do? And so, you can combine those or compute them at runtime via selectors, which think of selectors now as queries to the database.
[00:07:52] Hopefully, that was helpful. This is, in a very, like five minutes, you have a store, state flows down, event flows up into actions, into the reducer, which then modify state, which then flows down. And then, if you need to do an asynchronous thing that goes in effects and if you need to compute two models together, that happens via a selector.
>> Speaker 2: When you say FX, is that FX or effects?
>> Lukas Ruebbelke: E-F-F-E-C-T. So it's stands for, or it comes from side effects.
>> Lukas Ruebbelke: So for instance, if you needed to save something to the server, that's a side effect outside of the application. But this is also where I would put any kind of business logic that, when this thing happens, I need to capture it into some kind of transformation before I pass it on.
[00:08:44] And so, really, it's a library for handling side effects in your applications. And so, tripley, you have something go in, you do your logic with a side effect, and then once that's done, then you'll dispatch another action object, which would then go into the reducer, and say, okay now, here is the final state to put it in.