Reactive Angular with NgRx Basic Store Selectors
Transcript from the "Basic Store Selectors" Lesson
>> Lukas Ruebbelke: We are going to talk about selectors. So where we left off was with converting our reducer to use entity. But they changed the data structure. So pulling data directly from the store is a bit messy. So for instance if we looked here, this is prior to dumping out.
[00:00:21] We had to jump through some hoops to make that work. And so what we're going to do is we are going to introduce selectors that allows us to condense or abstract out some of this data manipulation here into what I would say is this composable query if you will.
[00:00:45] So to build this out, we're going to back to our reducer and we're going to build out a first layer of selectors. So what will happen here is I build out the low-level selectors in the feature reducer. And then I expose them in kind of the top level reducer, because ultimately is you may want to combine them.
[00:01:12] And so having all your selectors in kind of one place, especially when you're using computed or combined selectors, that's helpful. So I think of when you are dealing with selectors, have kind of a singular place you know kind of thinking of it as an APAN point. So will just build out our selectors here, I think that was almost Spanish like [FOREIGN].
>> Lukas Ruebbelke: So the first one is going to be I'll also precursor, selectors are just functions so they take some information and then they give you something else. So a very, very simple selector, and this is technically not a selector in the NGRX sense yet but if we wanted to get selected project ID, you would pass in state.
[00:02:07] And so this would be project state and return what, well, state dot SelectedProjectId.
>> Lukas Ruebbelke: Also, if we go to our adapter, and we click on this. That there's a GET selectors method that returns, some additional selectors for you, right out of the gate. So, for instance if you wanted all the IDs or entities, or more importantly if you wanted all of everything that it will return that for you.
[00:02:59] So what we are going to do is, pull this off using destructuring. So we go select Ids, selectEntities and selectAll. From adapter.getSelectors.
>> Lukas Ruebbelke: And then, because selectIds, selectEntties, selectAll, that's not super descriptive, we're going to export these with something a little bit,
>> Lukas Ruebbelke: More informative.
>> Lukas Ruebbelke: SelectIds,
>> Lukas Ruebbelke: ProjectEntities,
>> Lukas Ruebbelke: SelectAllProjects.
>> Lukas Ruebbelke: Here we go.
>> Lukas Ruebbelke: All right, so we built out these low-level selectors here. So these are just returning right from the state, it's returning specific things. But if we go into the top-level reducer. And here, let's spilled out the selectors that we want to expose to the outside world.
[00:04:43] So, am just going to go, projects selectors, and from here, we're going to create a feature selector, which is,
>> Lukas Ruebbelke: SelectProjectState equals,
>> Lukas Ruebbelke: FromProjects.ProjectState.
>> Lukas Ruebbelke: So what this does, I'm gonna break this down to just a second line here cuz this is a bit long, so we can just see it.
>> Lukas Ruebbelke: Is we're saying, I wanna get or select these feature off of the main state which is for the most part, the equivalent of this right here. So we're saying give me this piece of state.
>> Lukas Ruebbelke: And then from here, we can build out some additional selectors.
>> Lukas Ruebbelke: Select ProjectIds.
>> Lukas Ruebbelke: And this is going to take two parameters, so selectProjectState.
>> Lukas Ruebbelke: There we go. And,
>> Lukas Ruebbelke: From projects, selectProjectIds. Sort of saying, give us the state and then we're going to use this smaller selector down here to create the real selector. If we look in here.
>> Lukas Ruebbelke: This returns a memorized selector and I'll explain what that is in just a moment.
[00:07:11] So when state changes, that it runs through the selector and it value. So think of this as like well, like an something changes, it goes through, through the selector and it returns something new. But, if you make a selection and state has not changed, it's just going to return the last known state.
[00:07:44] So this is essentially the memo is station pattern, I believe or the memo pattern is that it's saying nothing has changed. So here's just the latest cache version. And so this is very, very efficient that it's only going to re-compute the data when one or more of these parameters changed.
[00:08:00] So, on one hand it's efficient that if nothing changes likely to re-compute and do. Especially if you are doing any kind of computation. It's just gonna give you the last value but on the flip side if something does change, it is going to push up a new value.
[00:08:17] So, on one hand because it doesn't, if it doesn't need to, awesome. But it will if it needs to, also awesome. So there's benefits on both sides. All right, so for the sake of time, let me just copy these down, and we'll just adjust these.
>> Lukas Ruebbelke: We'll go select Entities.
>> Lukas Ruebbelke: Entities, and we'll go selectAllProjects,
>> Lukas Ruebbelke: Okay. So we've created some low level selectors at the feature reducer. Then in our top level reducer, we have exposed them for consumption and this is, these are the selectors that we will interact directly with. So then I need to go to the here.
[00:09:20] And I need to make this available.
>> Lukas Ruebbelke: And then what we can do because it is available. Let's go here, take all of this, and we are going to replace it. With select and then selectAllProjects. Let's see where this coming from. There we go. And so now we're no longer having to kind of manually manipulate the data that's coming to our component.
[00:10:03] Is that using entity adapter you get some kind of pre built slaughters. More importantly is that in our topple over reducer, that we can handle any kind of computed data that we want to do. So that when it hits our component its in the exact shape that we need, which is critical.
[00:10:21] And so if you ever get to. This applies to any observable stream. And if you get to the bottom of an observable stream, like you are in your .subscribe block and you're fiddling with data, and that handler of like, I've got this data and then I need to transfer it.
[00:10:37] I need to do this stuff. This is very common when you have promises cuz there's not a concept of really chaining operators and promises. You can change promises and accomplish that but in observable it's very easy. And so what you want is by the end of the stream, when you hit your subscribe lock or when you piped in to a template pipe that your data is in exact shape that you need.
[00:11:03] So that is drop it in, and let it go. And so something like this just philosophically, from an architectural standpoint, makes a lot more sense than having to kind of fiddle and modify and transform the data to something I can use, especially at the component level.
>> Lukas Ruebbelke: And that is Selectors 101, so we're gonna revisit this in a little bit and I'll show you how to combine this selector.
[00:11:34] But pretty straightforward, just think of this is queries, and so you're allowed to query this slice of your data which is exactly, especially when at the low level we're saying, I wanna get just the select project ID. And then you're starting to filter this up, and compose these, and do slightly more sophisticated things.