Production-Grade Angular Actions, Store, Reducers & Selectors
Transcript from the "Actions, Store, Reducers & Selectors" Lesson
>> Actions are quite possibly the simplest part of the entire thing. An action is nothing more than an object that has a type and a payload, that's it. It's simply saying, this is what happened, and this is what we need to communicate in terms of that event. So, if I create a new widget, I'll have a createWidget action item with a type, and then I'll pass in that new widget to be processed.
[00:00:37] Now, what I want to point out here, notice that widgets, or the actions, it doesn't have a test, because there's nothing to them. There's no point in testing actions. They don't do anything. They're nothing more than a data structure. In fact, I think if I click on this, let me see here.
[00:01:01] So, what I'd like to do, in code, is basically click through and look at the type definitions. And it's really interesting what you can find. So, the interface for an action, the only thing that it has to have is type, that's it. There are actions that you simply are signaling something happened, you don't need to pass any data.
[00:01:24] And then from there, what you can do is, you can decorate that object with additional properties. But, an action is nothing more than a data structure with a type describing what it is, and then additional properties. All right, so, actions. Okay, cool, this is all we're using to, essentially, communicate.
[00:01:47] Then, within our facade, we are somewhat familiar with this. All this does is When something happens, it dispatches an action. So, facades do two things. Dispatches actions and allows you to select data from the store. Now, one thing I like to do, as well, is, I like to click on this.
[00:02:22] And if you look at the interface, it's select and dispatch. These are really the two methods that you would just use over, and over, and over. And this is the only way, or really, the only interaction that I ever have with the store, store.select, store.dispatch. So, so far, so good.
[00:02:48] We're communicating events via actions. And using store.select, we're able to get data back. So, where's this data coming from? Well, this gets a little interesting. So, we're getting a little more complex, but not by much. So here, we are defining our state, the shape of the state. What does our application state look like?
[00:03:20] Well, we have a selectedId, loaded, error. And there are some other things that come from EntityState. I'll explain what that is in just a moment. And all we're doing at this point is, we're defining the shape of the state and creating this entity adapter. Now, let's go down, and what does the adapter do?
[00:03:45] Has anyone ever tried to, and you've seen me do it today, at some point, but, manipulate a large collection? So, if I gave you, here's 100 things, and you need to find the one thing and you need to manipulate it. Well, it gets tedious, especially, when you're doing it over, and over, and over.
[00:04:05] So, what entity does, is it streamlines the ability to modify that collection. So, what you can do, for instance, is I want to set all of the widgets on the adapter, or I want to upsertOne. So, what that is, is I'm either gonna insert or update. [LAUGH] That's so clever.
[00:04:27] Add one, update one, remove one. This adapter is handling the underlying collection manipulation on your behalf. And so, on success, we're doing it on failure. We're just servicing an error message of some sort, we're handling it. So, now a reducer. All a reducer does, is it listens for an action based on the action type.
[00:04:56] It performs some operation and returns new state. So, you can just think of this as a single inflection point where, in this case, I want to reset the selected widget. Well, how would I do that? Well, I set the selectedId to null. And so when WidgetActions.resetSelectedWidget comes in, so, it's listening for an action type.
[00:05:24] It comes in, it performs that operation. And then it returns, essentially, new state to then be shared across the rest of the application. And so, if we stop and we just think for just a second, That we already are kind of familiar with this idea of separation between data and state.
[00:05:52] That we're querying the data and we're separating it from the commands and the querying of state, itself. So, data comes in, or actions come in and updates. And then, when under the hood, what does it do? In the previous module, how did we handle that? subject.next. So, if we look in the store, under the hood, it's an observable stream.
[00:06:21] That when you pass a new state, it's just propagating that down the observable stream to be updated. And so, think of it simply as an action comes in with some data, it updates the state, and then via that it's observable stream it communicates it back down. So, this is kind of the arc.
[00:06:42] At the top, actions come up, it hits the store, and then it's communicated back down via state. And then finally, well, I'll show you this real quick. Selectors are pretty straightforward. They're nothing more than really queries. They're functions that can take other selectors. That returns slices of state.
[00:07:06] And so, I wanna get, for instance, the SelectedWidgetId. Well, it takes the state and then returns just that slice. And so, it's a way to, essentially, write these prepackaged queries.