NgRx技巧1-带延迟加载的模块配置

前端开发2018-03-17

原文链接:https://medium.com/youngers-consulting/ngrx-tips-part-1-module-setup-with-lazy-loading-5dc8994b5a2d

如果您的 Angular 项目针对延迟加载进行了调整,并使用按需加载的独立模块进行加载,这些模块通过`StoreModule.forFeature(...) 定义了自己的 state 片段,您可以像这样定义根模块:

StoreModule.forRoot({} as any, { initialState: getInitialState });

但是,在我们使用所有状态初始化应用程序时,我们不提供任何 reducer。 这种方法的问题是,如果 reducer 不可用,那么任何尚未加载的功能将在操作分派时从状态中删除。

例如,假设我们的应用程序有一个“settings”区域和一个“Todos”区域,如果我们最初加载应用程序的“Todos”区域而不访问“settings”,该状态的一部分将在第一个操作分派时被移除,因为还没有可用的 reducer 来处理该功能的状态:

settings removed

由于 settings 功能尚未加载,因此 settings 部分被删除。

防止这种情况的一种方法(不影响应用程序中的所有 reducer)是,首先对所有功能设置一个默认 reducer,该 reducer 只取得当前状态并返回:

import { ActionReducerMap } from '@ngrx/store';
 
import * as settings from './settings/settings.actions';
import * as todos from './todos/todos.actions';
 
export interface ApplicationState {
  settings: settings.SettingsState;
  todos: todos.TodosState;
}
 
export function defaultReducer<T>(state: T) {
  return state;
}
 
export const initailReducerMap = {
  settings: defaultReducer,
  todos: defaultReducer,
} as ActionReducerMap<ApplicationState>;
 
export function getInitailState() {
  return {
    settings: settings.initialState,
    todos: todos.initialState,
  } as ApplicationState;
}

然后如下更新 NgRx 初始化:

StoreModule.forRoot(initialReducerMap, { initialState: getInitialState });

随着您的功能模块被加载,它们将替换默认的 reducer。 在此之前,他们会在任何派发的操作上返回初始状态,以防止这些功能从状态移除:

settings removed

“settings” 现在被保留

随着您的继续开发,如果添加新功能并更新了 ApplicationState 接口,它应该会导致编译错误,直到 initialReducerMap 更新。

然后,您的 store 选择器可以安全地假定功能状态部分将始终存在,而无需执行未定义(undefined)的检查。

在下一篇文章中,我将详细介绍选择器和测试。