If you’ve ever had to set up a store and reducers using ngrx (or any store framework), you know how tedious it can be to write an action for every slice of state you have. Wouldn’t it be easier if there was a pattern that allowed one set of actions to access and update most of your state? Well, you’re in luck because I’m about to show you how to write generic reducers and effects that can be re-used throughout your app! Our goal will be to write one reducer function and one effect that along with a state generator and selector that we will be able to reuse throughout an app.

This is part of a three part tutorial where I’ll take you through writing the functions that automatically generate a store, reducer, and selectors, how to update that store using effects and AJAX calls, and tie it all into a component. I’ll be using Angular 5 and ngrx here, but these same concepts can be applied to React + Redux / Flux and other state management libraries. In this article, I’ll set up the state structure, reducers to update that structure, and selectors to access it. I’ll be going forward assuming you have a basic understanding of Angular and how to use a state management library.

Generating Your State Object

The very first thing we have to do in this process is to set-up a function that will create the skeleton to hold our data. The function will take in an object that describes the data our component will need and return a new data structure. We’ll assume a consistent data structure throughout our component to make the process simpler.

The generateInitialData function takes in an object and returns a new object with the same structure but with { data: undefined, status: undefined } at the leaf nodes ( where the value at a key equals true ). This is the data structure we will create our components around. As a side note, it is possible to customize the initial state for each key by placing that data in place of the true values, but I’ll leave that for you to figure out.

Now that we have our state structure, we need a way to update it when we receive new data from the effects (that we’ll write later). We’ll be accomplishing that by…

Writing the Reducer Function

Our reducer function will be pretty straight-forward since it only has to do a couple of things: access any slice of state and update that slice with our new data. The first thing we’ll do is define the interface for the action data structure that we’ll be using.

To update our state the action needs to hold the data that should be placed in a certain slice of state, and the path to that slice of state. The data can be of any format (array, string, object, etc.), you just need to write your components accordingly to use that format. The path needs to be a string, or array of strings, that can be used with lodash’s get function. This is the crux to how we will be updating arbitrary pieces of state through one reducer function. Now let’s look at the code for the reducer.

Starting from the top, our we have the higher-order function, reducerWrapper, that takes in the string, featureName, which is what will be used to distinguish between different feature modules in our app, and the initialState object, which is created by our createInitialData function from earlier. The return value is a function, which ends up being used as our reducer.

Currently, the reducer handles two situations, a successful AJAX call and a failed one. This reducer is generic in that it expects to receive the new data for the state from elsewhere, but you can make it more specific to handle your own use case by modifying this same pattern. You maybe wondering where the data is coming from and where the AJAX call is being done, but don’t worry about that for now ( the answer is from the effects just in case you’re like me and not knowing would bother you ).

Accessing the State Through Selectors

The next thing on our plate is to create selectors to access our state slices. And since our goal is to automate as much of the store set-up as we can, we’re going to write a function that takes our state structure ( what we pass to the generateInitialData function ) and returns an object of selectors. But before I go into, I’ll give a quick overview of how selectors work in ngrx since it took me a while to understand them when I was creating this pattern.

Essentially, what a selector does is map from a high level slice of state to a lower-level one. It’s the equivalent of the following pattern with objects, but for observables:

const getInterests = (anObject) => anObject['interests'];
const getTvInterests = (anObject) => getInterests(anObject)['tv'];

A selector takes in an object (state) and returns a property from it. However, like the functions above, selectors can only go down one level of an object at a time so if you need to go grab something from deep in your state, your code is going to look something like this:

That is pretty verbose, and we can automate a lot of that away since there is a simple pattern to getting to the slice of state we want (use createFeatureSelector on the root state and createSelector afterwards) and we already know what structure our state will have.

The structure of the inner function should look somewhat familiar since it’s pattern is very similar to generateInitialData from before. The key points to this function are we use createFeatureSelector first to choose the slice of state we want from our feature module, and go from there. At every level of the object, we have a selector property which returns a selector function that will get us to that slice of state. So if our state looks like

This reduces the amount of code we have to write by A LOT since we can re-use this function with all of our state structures and it’s usage directly mirrors the original state structure we pass it. So if we want to access the sports slice of our state, all we would have to do is pass selectorMap.interests.sports.selector to the store selector function and we’d have the data we need.

Wrapping Up

To quickly summarize what we accomplished in this article:

  • Wrote a function to turn our state structure into our initial data object
  • Generalized a reducer function to be reusable across our app
  • Created a way to easily access our state slice with low code overhead

In the next article, we will:

  • Use effects to update our state
  • Tie AJAX calls into our effects

Thank you for reading and I hope I was able to teach you something knew! If you have any questions or comments please feel free to leave a comment or contact me on Twitter Murad Khan and I’ll reply as soon as possible.