【问题标题】:IONIC & NGRX: Troubles with initial stateIONIC & NGRX:初始状态的问题
【发布时间】:2018-04-20 21:19:47
【问题描述】:

我在 Ionic 应用程序中遇到了 Ngrx 问题。
我的商店由两种类型的对象“Compteur”和“Prise[]”组成。
我将ngrx实体用于“Prise”对象,效果很好。 但是对于 Compteur 对象,初始状态似乎是未定义的,因此,我的选择器使应用程序崩溃。

如果我不尝试订阅,商店会完美构建。
我怎样才能解决这个问题? 它是如何工作的?

我有这个错误:

Runtime Error
Cannot read property 'compteur' of undefined
Stack
TypeError: Cannot read property 'compteur' of undefined
    at http://localhost:8100/build/main.js:100:145
    at http://localhost:8100/build/vendor.js:27678:30
    at memoized (http://localhost:8100/build/vendor.js:27615:28)
    at defaultStateFn (http://localhost:8100/build/vendor.js:27649:39)
    at http://localhost:8100/build/vendor.js:27681:36
    at MapSubscriber.memoized [as project] (http://localhost:8100/build/vendor.js:27615:28)
    at MapSubscriber._next (http://localhost:8100/build/vendor.js:56535:35)
    at MapSubscriber.Subscriber.next (http://localhost:8100/build/vendor.js:22085:18)
    at MapSubscriber._next (http://localhost:8100/build/vendor.js:56541:26)
    at MapSubscriber.Subscriber.next (http://localhost:8100/build/vendor.js:22085:18)

在我调用选择器的 app.component.ts 中:

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  @ViewChild(Nav) nav: Nav;

  rootPage: any = HomePage;
  compteur$: Observable<Compteur>;
  prises$: Observable<Prise[]>;
  pages: Array<{ title: string, component: any }>;

  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public store: Store<AppState>) {
    this.initializeApp();
    // used for an example of ngFor and navigation
    this.pages = [
      {title: 'Accueil', component: HomePage},
      {title: 'Configuration', component: ListPage}
    ];


    this.compteur$ = this.store.select(fromCompteur.getCompteur);
    this.compteur$.subscribe(()=> {
       console.log("NOT WORKING");
    });

    this.prises$ = this.store.select(fromPrise.getPrise);
    this.prises$.subscribe(()=>{
      console.log("WORKING");
    });
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();

      this.store.dispatch(new fromCompteurActions.LoadAction());
      this.store.dispatch(new fromPriseActions.LoadAction());
    });
  }

  openPage(page) {
    this.nav.setRoot(page.component);
  }
}

compteur.actions.ts:

export const LOAD_COMPTEUR = "[COMPTEUR] LOAD";
export const LOAD_COMPTEUR_COMPLETED = "[COMPTEUR] LOAD COMPLETED";
export const UPDATE_COMPTEUR = "[COMPTEUR] UPDATE";

export class LoadAction implements Action {
  readonly type = LOAD_COMPTEUR;
  constructor(){};
}

export class LoadCompletedAction implements Action {
  readonly type = LOAD_COMPTEUR_COMPLETED;
  constructor(public payload: {compteur: Compteur}){};
}

export class UpdateAction implements Action {
  readonly type = UPDATE_COMPTEUR;
  constructor(public payload: {compteur: Compteur}){};
}

export type compteurActionType =
  | LoadAction
  | LoadCompletedAction
  | UpdateAction
  ;

compteur.reducer.ts

const initialState : CompteurState = {
  compteur: null,
  loading: false
};

export function reducer(state = initialState,
                        action: fromCompteur.compteurActionType): CompteurState{
  switch (action.type){
    case fromCompteur.UPDATE_COMPTEUR: {
      return {
        compteur: action.payload.compteur,
        loading: false
      };
    }
    case fromCompteur.LOAD_COMPTEUR: {
      return {...state,
      loading: true
      };
    }
    case fromCompteur.LOAD_COMPTEUR_COMPLETED: {
      return {
        compteur: action.payload.compteur,
        loading: false
      };
    }
    default: {
      return state;
    }
  }

}

export const getCompteurState = createFeatureSelector<CompteurState>('compteur');
export const getCompteur = createSelector(getCompteurState, (state: CompteurState) => state.compteur);

export const getLoading = createSelector(getCompteurState, (state: CompteurState) => state.loading);

reducer/index.ts

export const reducers: ActionReducerMap<AppState> = {
  priseState: priseReducer.reducer,
  compteurState: compteurReducer.reducer
};

export function logger(reducer: ActionReducer<AppState>): ActionReducer<AppState> {
  return function(state: AppState, action: any): AppState {
    console.log('state', state);
    console.log('action', action);
    return reducer(state, action);
  };
}

export const metaReducers: MetaReducer<AppState>[] = [logger];

compteur.effects.ts

@Injectable()
export class CompteurEffects {

  constructor(private actions$: Actions,
              private dataService : DataService){};

  @Effect()
  loadCompteur$: Observable<Action> = this.actions$
    .ofType(fromCompteur.LOAD_COMPTEUR)
    .switchMap(()=>
      this.dataService.getCompteur()
        .map(data => new fromCompteur.LoadCompletedAction({ compteur: data })
        )
    );


}

app.state.ts

export interface AppState {
  priseState: PriseState;
  compteurState: CompteurState;
}

export interface PriseState extends EntityState<Prise>{
  selectedPriseId: string | number | null,
  loading: boolean
}

export interface CompteurState {
  compteur: Compteur,
  loading: boolean
}

package.json

"dependencies": {
    "@angular/common": "5.0.3",
    "@angular/compiler": "5.0.3",
    "@angular/compiler-cli": "5.0.3",
    "@angular/core": "5.0.3",
    "@angular/forms": "5.0.3",
    "@angular/http": "5.0.3",
    "@angular/platform-browser": "5.0.3",
    "@angular/platform-browser-dynamic": "5.0.3",
    "@ionic-native/core": "4.4.0",
    "@ionic-native/splash-screen": "4.4.0",
    "@ionic-native/status-bar": "4.4.0",
    "@ionic/storage": "2.1.3",
    "@ngrx/core": "^1.2.0",
    "@ngrx/effects": "^5.2.0",
    "@ngrx/entity": "^5.2.0",
    "@ngrx/store": "^5.2.0",
    "@ngrx/store-devtools": "^5.2.0",
    "chart.js": "^2.7.2",
    "ionic-angular": "3.9.2",
    "ionicons": "3.0.0",
    "ng2-charts": "^1.6.0",
    "rxjs": "5.5.2",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.18"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.1.8",
    "typescript": "2.4.2"
  }

【问题讨论】:

  • 你在reducer中捕获UPDATE_COMPTEUR动作,当你调度它时你指定一个有效载荷吗?
  • 是的,但我无法测试更新,因为我的应用在启动时崩溃了。
  • 能否在reducer中添加这一行在切换前并分享结果:console.log(action.type + ' - ' + action.payload);
  • LOAD_COMPTEUR 不需要有效负载,因此日志为:@ngrx/store/init - undefined
  • 但我不认为问题出在有效负载上,因为如果我不尝试订阅我的 compteur 存储,load 和 load_complete 任务会按预期使用 compteur 数据运行。

标签: angular ionic-framework redux ngrx


【解决方案1】:

好的,我发现了我的错误:
我在 compteur.reducer.ts 中犯了一个错误
只需要替换这个:

export const getCompteurState = createFeatureSelector<CompteurState>('compteur');

通过

export const getCompteurState = createFeatureSelector<CompteurState>('compteurState');

【讨论】:

    猜你喜欢
    • 2021-06-26
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2023-03-04
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    相关资源
    最近更新 更多