Monday, June 25, 2018

when selectors call other selectors in the NgRx Redux pattern

Let's say you have a const variable like so in a breakfast.selector.ts file:

export const getBreakfast = createSelector(getEggs, getToast, getBacon, (eggs:
      Array<Egg>, toast: Array<BreadSlice>, bacon: Array<BaconStrip>):
      BreakfastModel =>
   ({
      name: eggs.length === 0 ? "Ghetto Breakfast" : bacon.length === 0 ? "Eggs
            & Sausage" : "Eggs & Bacon",
      numberOfEggs: eggs.length,
      hasBacon: bacon.length > 0,
      hasSausage: bacon.length === 0,
      hasOrangeJuice: true,
      toast: toast
   }));

 
 

...and an import to empower createSelector like so:

import { createSelector } from '@ngrx/store';

 
 

Yet, elsewhere is code, the selector is called like so in the name of fishing the BreakfastModel out of the store:

return this.store.select(getBreakfast).take(1);

 
 

The thing to notice is that it is called with no variables in spite of the fact that there is so very much being handed into createSelector. This should prompt the question "Where does all of the other stuff come from?" Alright, there will always be two or more variables handed into createSelector. The last of n number of variables will be a function that takes n-1 variables and returns a model, in this case BreakfastModel, and the n-1 variables are hydrated by the variables upstream of the function variable such that, in our case, getEggs populates eggs, getToast fills in toast, and getBacon, as the name suggest, gets us bacon. So what are getEggs, getToast, and getBacon? They would be other const variables. They too may be made with createSelector like so:

export const getEggs = createSelector(inventoryKitchen, (kitchen: Kitchen):
      Array<Egg> =>
   {
      return kitchen.eggs;
   });

 
 

Obviously, not every createSelector can be hydrated by a createSelector. There has to be something else somewhere upstream of all that. In the case immediately above inventoryKitchen could just be a function assigned to a const variable. If there is just a function returning an object at the mouth of the river, the createSelector machinery must also be trying to pull stuff of the shape handed in from the store in lieu of just using the default object handed in. I'm not sure how that works just yet. It's magic to me.

No comments:

Post a Comment