StefanSinapov
10/31/2016 - 3:45 PM

store-v3.md

@ngrx/store v3

Problems:

  • Users want to compose reducer tree across modules
  • Idea of a single reducer function makes it difficult for the library to dynamically augment the shape of the state tree
  • Turning control over to the library to build the root reducer limits the use of meta-reducers
  • Feature modules may inadvertently collide with the state of the root module
  • Library authors may want to leverage @ngrx/store in their projects and provide an easy way for their libraries to work in apps already built with @ngrx/store

Proposal:

  • Add a fractal state mechanism for isolating child modules to @ngrx/store
  • Shift control over creating the root reducer function to @ngrx/store. Developers would have to provide an action reducer map instead of a root reducer.
  • Allow developers to optionally provide a reducerFactory function for turning an action reducer map into an action reducer.
  • Scope Store such that a child module's services and components only have access to the state of that module.
  • All actions continue to move through a global dispatcher. Every reducer continues to receive every action.
  • Add an API for dynamically inserting a reducer at a specific key
  • If a feature module is isolated (as in there is no parent module that uses @ngrx/store), intelligently work like a root module

At the core this is still redux making it easy to instrument, rehydrate, etc.

API:

Root module:

@NgModule({
  imports: [
    StoreModule.forRoot({ todos: todoReducer, layout: layoutReducer }, {
      initialState?: { ... },
      reducerFactory?: combineReducers
    })
  ]
})
export class AppModule { }

Global state shape:

{
  todos: { ... },
  layout: { ... }
}

Child module:

@NgModule({
  imports: [
    StoreModule.forFeature('feature', { blog: blogReducer }, {
      initialState?: { ... },
      reducerFactory?: combineReducers
    })
  ]
})
export class FeatureModule { }

New global state shape:

{
  todos: { ... },
  layout: { ... },
  feature: {
    blog: { ... }
  }
}

Injecting Store in a component or service belonging to FeatureModule only gives you access to the local state:

{
  blog: { ... }
}

Implementation

I have a rough but complete implementation available in a branch here: https://github.com/MikeRyan52/store/tree/feat/fractal-statemanagement

Prior Art: