Understanding the magic behind @ngrx/store

Hey, @andrei.gatej, this looks like a monumental work. Congrats for the efforts!

It occurred to me that it might be useful as a reference. So more anchors would be useful. For example -
Action Creator - Just Type
Action Creator - Type and Props
Action Creator - Type and Props constructor

2 Likes

Hello @gparlakov, this is a great suggestion! I’ll look into it. Thank you!

Sure, @andrei.gatej, seems useful to have index/contents on top.

I had a question about

{ provide: REDUCERS_TOKEN, useValue: { foo: fooReducer } }

Can we use multi: true with that?

@gparlakov, I haven’t tried it, but I don’t think it would work.

Taking this snippet as an example:

{ provide: REDUCERS_TOKEN, useValue: { foo: fooReducer } }
/* ... */
StoreModule.forRoot(REDUCERS_TOKEN)

The _createStoreReducers function is responsible for resolving the reducers

export function _createStoreReducers(
  injector: Injector,
  reducers: ActionReducerMap<any, any>
) {
  return reducers instanceof InjectionToken ? injector.get(reducers) : reducers;
}

The value of _createStoreReducers will be assigned to INITIAL_REDUCERS, which is then injected in ReducerManager:

@Inject(INITIAL_REDUCERS) private reducers: ActionReducerMap<any, any>,

As you can see, the type is ActionReducerMap. Had we used a multi token, the type would be ActionReducerMap<any, any>[], which I don’t I think it’s suitable, considering how the injected reducers are used later.


The same reasoning should be applied when using StoreModule.forFeature('featureName', REDUCERS_TOKEN)

Here’s the _createFeatureReducers function which resolves the reducers

export function _createFeatureReducers(
  injector: Injector,
  reducerCollection: ActionReducerMap<any, any>[]
) {
  const reducers = reducerCollection.map(reducer => {
    return reducer instanceof InjectionToken ? injector.get(reducer) : reducer;
  });

  return reducers;
}

where reducerCollection is the value of _FEATURE_REDUCERS, which is multi token:

{ provide: _FEATURE_REDUCERS, multi: true, useValue: reducers },

so, this should explain why reducerCollection has the ActionReducerMap<any, any>[] type. _FEATURE_REDUCERS is of type ActionReducerMap<any, any>, but because it’s at the same time a multi token, it becomes ActionReducerMap<any, any>[].

1 Like

Hey @andrei.gatej, just wringing to say thanks. This was super useful. Very well written article. I feel this is even more useful than ngrx documentation itself!

Thank you, @cquiros. I’m glad you found it useful!