在 @ngrx/store 4.0 中提供 root reducer

Posted

技术标签:

【中文标题】在 @ngrx/store 4.0 中提供 root reducer【英文标题】:Providing root reducer in @ngrx/store 4.0 【发布时间】:2017-12-26 11:54:29 【问题描述】:

在@ngrx/store 2.0 中,我们可以将根reducer 作为一个函数提供,然后我们在应用程序中拆分我们的逻辑。在我更新到@ngrx/store 4.0 之后,我不能再使用这个功能了,我可以看到减速器需要是一个减速器的映射,它将在状态的相同键下创建对象。有没有办法在@ngrx/store 4.0 中使用旧的行为?自己的方式。此外,应用程序被拆分为多个延迟加载的路由,这些路由在某些情况下会重用来自另一个功能的数据。

 StoreModule.provideStore(reducer, 
      auth: 
        loggedIn: true
      
    )

StoreModule.forRoot(reducers, 
      initialState: 
        auth: 
          loggedIn: true
        
      
    )

我需要reducers 成为一个获取完整状态并将其分派到正确的reducer 的函数,有没有办法实现这种行为?

【问题讨论】:

【参考方案1】:

StoreModuleforRoot() 函数接受 reducerFactory,可以按如下方式使用:

export function myReducerFactory(reducers: any, initState: any) 
  return (state = myInitialState, action) => myCustomReducer(state, action);


@NgModule(
  // ...
  imports: [
    StoreModule.forRoot(null,  reducerFactory: myReducerFactory )
  ]
  // ...
)
export class AppModule 

【讨论】:

【参考方案2】:

在我再次查看 ngrx 存储库后,我想通了。为了达到想要的结果,我们需要用新的实现替换 @ngrx/store 减速器工厂。我注入了一个新的减速器工厂,现在应用程序像以前一样工作。简单的代码示例说明如何更换reducer factory吧。

// This factory replaces @ngrx combine reducers so we can manage how we split the keys inside the state
export function combineReducersFactory(
    reducers: any,
    initialState: any = 
): ActionReducer<any, Action> 
    return function combination(state = initialState, action) 
        const nextState: any = reducers(state, action);
        return nextState !== state ? nextState : state;
    ;


export const NG_RX_STORE_PROVIDER = [
    StoreModule.forRoot(rootReducer, createEmptyState()),
];

export const NG_RX_REDUCER_FACTORY = [
    
        provide: REDUCER_FACTORY,
        useFactory: () => combineReducersFactory
    
];

@NgModule(
    imports: [
        ...NG_RX_STORE_PROVIDER
    ],
    declarations: [...APP_COMPONENTS, ...AG_GRID_COMPONENTS],
    providers: [...NG_RX_REDUCER_FACTORY]
)
export class AppModule 

【讨论】:

【参考方案3】:

您可以设置meta reducer 来接收每个事件并从其根目录操作状态。这是设置它的示例方法:

const myInitialState = 
  // whatever you want your initial state to be
;

export function myMetaReducer(
  reducer: ActionReducer<RootStateType>
): ActionReducer<RootStateType> 
  return function(state, action) 
    if (iWantToHandleThisAction) 
      state = doWhatIWantWith(state);
    
    return reducer(state, action);
  ;


@NgModule(
  imports: [
    StoreModule.forRoot(myInitialState,  metaReducers: [myMetaReducer] )
  ]
)
export class AppModule 

【讨论】:

myInitialState 未定义且参数肯定错误 myInitialState 替换为 即可。这个参数不是初始状态,而是ActionReducerMap。由于在这种情况下,没有任何东西被映射并且所有东西都由元减速器处理,所以它可以工作。 抱歉 - 我的意思是作为您想要作为初始状态传入的任何内容的占位符 - 将进行编辑以使其更清晰。【参考方案4】:

这对我有用:

// your old reducer that handled slicing and dicing the state
export function mainReducer(state = , action: Action) 
    // ...
    return newState;


// new: metaReducer that just calls the main reducer
export function metaReducer(reducer: ActionReducer<AppState>): ActionReducer<AppState> 
    return function (state, action) 
        return MainReducer(state, action);
    ;


// new: MetaReducer for StoreModule.forRoot()
export const metaReducers: MetaReducer<any>[] = [metaReducer];

// modified: app.module.ts
@NgModule(
    // ...
    imports: [
        // neglect first parameter ActionReducerMap, we don't need this
        StoreModule.forRoot(, 
            metaReducers: metaReducers,
            initialState: INITIAL_STATE // optional
        ),
    ]
)

【讨论】:

以上是关于在 @ngrx/store 4.0 中提供 root reducer的主要内容,如果未能解决你的问题,请参考以下文章

Ngrx Store 作为提供者中的依赖关系导致循环依赖

错误:商店没有提供者!在@ngrx 4.x

如何在 @ngrx/store 的 createAction 中使用数组作为参数

安装@ngrx/store 时如何清除错误?

如何重置ngrx/store的所有状态?

将 ngrx/Store 集成到现有的 Angular 项目中