Skip to content

Commit

Permalink
feat(Store): Simplified API for adding meta-reducers
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonroberts committed Jul 18, 2017
1 parent b9776ea commit c55eff8
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 13 deletions.
10 changes: 5 additions & 5 deletions docs/store/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export function getInitialState() {

## Reducer Factory

@ngrx/store composes your map of reducers into a single reducer. Use the `reducerFactory`
configuration option to provide a composed action reducer factory:
@ngrx/store composes your map of reducers into a single reducer. Use the `metaReducers`
configuration option to provide an array of meta-reducers that are composed from right to left.

```ts
import { StoreModule, combineReducers, compose } from '@ngrx/store';
Expand All @@ -62,11 +62,11 @@ function debug(reducer) {
}
}

const debugReducerFactory = compose(debug, combineReducers);
const metaReducers = [debug];

@NgModule({
imports: [
StoreModule.forRoot(reducers, { reducerFactory: debugReducerFactory })
StoreModule.forRoot(reducers, { metaReducers })
]
})
export class AppModule {}
Expand All @@ -77,7 +77,7 @@ export class AppModule {}
Store uses fractal state management, which provides state composition through feature modules,
loaded eagerly or lazily. Provide feature states using the `StoreModule.forFeature` method. This
method defines the name of the feature state and the reducers that make up the state. The same `initialState`
and `reducerFactory` configuration options are available.
and `metaReducers` configuration options are available.

```ts
// feature.module.ts
Expand Down
4 changes: 2 additions & 2 deletions example-app/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { CoreModule } from './core/core.module';
import { AuthModule } from './auth/auth.module';

import { routes } from './routes';
import { reducers } from './reducers';
import { reducers, metaReducers } from './reducers';
import { schema } from './db';

import { AppComponent } from './core/containers/app';
Expand All @@ -37,7 +37,7 @@ import { environment } from '../environments/environment';
* meta-reducer. This returns all providers for an @ngrx/store
* based application.
*/
StoreModule.forRoot(reducers),
StoreModule.forRoot(reducers, { metaReducers }),

/**
* @ngrx/router-store keeps router state up-to-date in the store.
Expand Down
20 changes: 19 additions & 1 deletion example-app/app/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
ActionReducerMap,
createSelector,
createFeatureSelector,
compose,
ActionReducer,
combineReducers,
Action,
Expand Down Expand Up @@ -37,6 +36,25 @@ export const reducers: ActionReducerMap<State> = {
layout: fromLayout.reducer,
};

// console.log all actions
export function logger(reducer: ActionReducer<State>): ActionReducer<any, any> {
return function(state: State, action: any): State {
console.log('state', state);
console.log('action', action);

return reducer(state, action);
};
}

/**
* By default, @ngrx/store uses combineReducers with the reducer map to compose
* the root meta-reducer. To add more meta-reducers, provide an array of meta-reducers
* that will be composed to form the root meta-reducer.
*/
export const metaReducers: ActionReducer<any, any>[] = !environment.production
? [logger]
: [];

/**
* Layout Reducers
*/
Expand Down
4 changes: 3 additions & 1 deletion modules/store/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export {
} from './models';
export { StoreModule } from './store_module';
export { Store } from './store';
export { combineReducers, compose } from './utils';
export { combineReducers, compose, createReducerFactory } from './utils';
export { ActionsSubject, INIT } from './actions_subject';
export {
ReducerManager,
Expand All @@ -24,10 +24,12 @@ export {
export { State, StateObservable, reduceState } from './state';
export {
INITIAL_STATE,
_REDUCER_FACTORY,
REDUCER_FACTORY,
INITIAL_REDUCERS,
STORE_FEATURES,
_INITIAL_STATE,
META_REDUCERS,
} from './tokens';
export {
StoreRootModule,
Expand Down
1 change: 1 addition & 0 deletions modules/store/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface StoreFeature<T, V extends Action = Action> {
reducers: ActionReducerMap<T, V> | ActionReducer<T, V>;
reducerFactory: ActionReducerFactory<T, V>;
initialState?: InitialState<T>;
metaReducers?: ActionReducer<any, any>[];
}

export interface Selector<T, V> {
Expand Down
8 changes: 6 additions & 2 deletions modules/store/src/reducer_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
StoreFeature,
} from './models';
import { INITIAL_STATE, INITIAL_REDUCERS, REDUCER_FACTORY } from './tokens';
import { omit } from './utils';
import { omit, createReducerFactory } from './utils';
import { ActionsSubject } from './actions_subject';

export abstract class ReducerObservable extends Observable<
Expand All @@ -34,13 +34,17 @@ export class ReducerManager extends BehaviorSubject<ActionReducer<any, any>>
addFeature({
reducers,
reducerFactory,
metaReducers,
initialState,
key,
}: StoreFeature<any, any>) {
const reducer =
typeof reducers === 'function'
? reducers
: reducerFactory(reducers, initialState);
: createReducerFactory(reducerFactory, metaReducers)(
reducers,
initialState
);

this.addReducer(key, reducer);
}
Expand Down
17 changes: 15 additions & 2 deletions modules/store/src/store_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import {
StoreFeature,
InitialState,
} from './models';
import { combineReducers } from './utils';
import { compose, combineReducers, createReducerFactory } from './utils';
import {
INITIAL_STATE,
INITIAL_REDUCERS,
REDUCER_FACTORY,
_REDUCER_FACTORY,
STORE_FEATURES,
_INITIAL_STATE,
META_REDUCERS,
} from './tokens';
import { ACTIONS_SUBJECT_PROVIDERS, ActionsSubject } from './actions_subject';
import {
Expand Down Expand Up @@ -62,6 +64,7 @@ export class StoreFeatureModule implements OnDestroy {
export type StoreConfig<T, V extends Action = Action> = {
initialState?: InitialState<T>;
reducerFactory?: ActionReducerFactory<T, V>;
metaReducers?: ActionReducer<T, V>[];
};

@NgModule({})
Expand Down Expand Up @@ -89,11 +92,20 @@ export class StoreModule {
? { provide: INITIAL_REDUCERS, useExisting: reducers }
: { provide: INITIAL_REDUCERS, useValue: reducers },
{
provide: REDUCER_FACTORY,
provide: META_REDUCERS,
useValue: config.metaReducers ? config.metaReducers : [],
},
{
provide: _REDUCER_FACTORY,
useValue: config.reducerFactory
? config.reducerFactory
: combineReducers,
},
{
provide: REDUCER_FACTORY,
deps: [_REDUCER_FACTORY, META_REDUCERS],
useFactory: createReducerFactory,
},
ACTIONS_SUBJECT_PROVIDERS,
REDUCER_MANAGER_PROVIDERS,
SCANNED_ACTIONS_SUBJECT_PROVIDERS,
Expand Down Expand Up @@ -130,6 +142,7 @@ export class StoreModule {
reducerFactory: config.reducerFactory
? config.reducerFactory
: combineReducers,
metaReducers: config.metaReducers ? config.metaReducers : [],
initialState: config.initialState,
},
},
Expand Down
4 changes: 4 additions & 0 deletions modules/store/src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ import { OpaqueToken } from '@angular/core';
export const _INITIAL_STATE = new OpaqueToken('_ngrx/store Initial State');
export const INITIAL_STATE = new OpaqueToken('@ngrx/store Initial State');
export const REDUCER_FACTORY = new OpaqueToken('@ngrx/store Reducer Factory');
export const _REDUCER_FACTORY = new OpaqueToken(
'@ngrx/store Reducer Factory Provider'
);
export const INITIAL_REDUCERS = new OpaqueToken('@ngrx/store Initial Reducers');
export const META_REDUCERS = new OpaqueToken('@ngrx/store Meta Reducers');
export const STORE_FEATURES = new OpaqueToken('@ngrx/store Store Features');
11 changes: 11 additions & 0 deletions modules/store/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,14 @@ export function compose(...functions: any[]) {
return rest.reduceRight((composed, fn) => fn(composed), last(arg));
};
}

export function createReducerFactory(
reducerFactory: ActionReducerFactory<any, any>,
metaReducers?: ActionReducer<any, any>[]
): ActionReducerFactory<any, any> {
if (Array.isArray(metaReducers) && metaReducers.length > 0) {
return compose.apply(null, [...metaReducers, reducerFactory]);
}

return reducerFactory;
}

0 comments on commit c55eff8

Please sign in to comment.