我正在尝试解决我在我的一个应用程序中使用ngrx遇到的问题。 由于这是我的第一个ngrx项目,因此我按照ngrx示例应用程序构建了应用程序实体的操作,效果和缩减器。
我的应用程序中有一个患者实体,我已经创建了以下操作和reducer:
患者行动:
import { Action } from '@ngrx/store';
import { IPatient } from '../../../interfaces/';
export const LOAD_PATIENT = '[Patient] Load';
export const ADD_PATIENT = '[Patient] Add';
export const DELETE_PATIENT = '[Patient] Delete';
export class LoadPatientAction implements Action {
readonly type = LOAD_PATIENT;
}
export class AddPatientAction implements Action {
readonly type = ADD_PATIENT;
constructor(public patient: IPatient) { }
}
export class DeletePatientAction implements Action {
readonly type = DELETE_PATIENT;
constructor(public patient: IPatient) { }
}
export type PatientActions = LoadPatientAction
| AddPatientAction
| DeletePatientAction;
减速器:
import { createSelector } from 'reselect';
import { IPatient, IPatientState } from '../../../interfaces/';
import { PatientState } from '../../../models/';
import { patientActions } from '../../actions/patient/';
export interface State {
patient: IPatient | null;
loaded: boolean;
}
export const initialState: State = {
patient: null,
loaded: false
}
export function patientReducer(state = initialState,
action: patientActions.PatientActions): State {
switch (action.type) {
case patientActions.LOAD_PATIENT: {
return Object.assign({}, state, { loaded: true });
}
case patientActions.ADD_PATIENT: {
const patient = action.patient;
if (state.patient.id === patient.id ) { return state; }
return { patient: patient, loaded: false };
}
case patientActions.DELETE_PATIENT: {
const patient: IPatient = action.patient;
return state.patient && (patient.id === state.patient.id) ?
{ patient: null, loaded: false } : state;
}
default: { return state; }
}
}
export const getPatient = (state: State) => state.patient;
export const isPatientLoaded = (state: State) => state.loaded;
reducers的index.ts文件如下所示。 (我省略了与患者实体无关的所有部分......):
import { IDpxStates,
IUnitState,
ICollectionState,
ISearch,
ILayout,
ILayoutTypes,
IPatient,
IDpxReducers } from '../../interfaces/';
import { DpxState, DpxStateReducer } from '../../models/';
import { createSelector } from 'reselect';
import { State, Store, ActionReducer } from '@ngrx/store';
import * as fromRouter from '@ngrx/router-store';
import { environment } from '../../../environments/environment';
import { storeFreeze } from 'ngrx-store-freeze';
import { combineReducers } from '@ngrx/store';
import * as fromLayout from './layout/layout.reducer';
import * as fromPatient from './patients/patient/patient.reducer';
const reducers: IDpxReducers = {
layoutReducer: fromLayout.layoutReducer,
patientReducer: fromPatient.patientReducer,
routerReducer: fromRouter.routerReducer
}
const developmentReducer: ActionReducer<IDpxStates> = compose(storeFreeze, combineReducers)(reducers);
const productionReducer: ActionReducer<IDpxStates> = combineReducers(reducers);
export function reducer(state: any, action: any) {
if (environment.production) {
return productionReducer(state, action);
} else {
console.log(developmentReducer(state, action));
return developmentReducer(state, action);
}
}
export const getPatient = (state: IDpxStates) => state.patient;
export const isPatientLoaded = (state: IDpxStates) => state.loaded;
IDpxStates和IDpxReducers接口:
export interface IDpxReducers {
...
readonly patientReducer: (state: IPatientState, action: patientActions.PatientActions) => IPatientState;
...
}
export interface IDpxStates {
...
readonly patientState: IPatientState;
...
}
export interface IPatientState {
patient: IPatient | null;
loaded: boolean;
}
现在我尝试将患者从仪表板容器中取出,然后将其传递给标题组件:
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Router } from '@angular/router';
import { FormGroup } from '@angular/forms';
import { Observable } from 'rxjs/Rx';
import { Store } from '@ngrx/store';
import * as reducer from '../../state/reducers/';
import * as layout from '../../state/actions/layout/';
import { patientActions } from '../../state/actions/patient/';
import { IDpxStates, IPatient } from '../../interfaces/';
@Component({
selector: 'app-dashboard',
changeDetection: ChangeDetectionStrategy.OnPush,
template:
`
<app-header
[routerLinks]="routerLinks"
[patient]="patient$ | async"
(addPatient)="openAddPatient()"
(addDrug)="openAddDrug()"
(addIndication)="openAddIndication()">
</app-header>
<router-outlet></router-outlet>
`,
styleUrls: ['_dashboard.component.scss']
})
export class DashboardComponent {
patient$: Observable<IPatient>;
showAddPatient$: Observable<boolean>;
showAddDrug$: Observable<boolean>;
showAddIndication$: Observable<boolean>;
routerLinks: {addPatient: string, addDrug: string, addIndication: string} =
{addPatient: 'patient/add',
addDrug: 'patient/${patient$.id}/drugs/add',
addIndication: 'patient/${patient$.id}/indications/add'};
constructor(private _store: Store<IDpxStates>, private _router: Router) {
this.patient$ = this._store.select(reducer.getPatient);
this.showAddPatient$ = this._store.select(reducer.getVisible);
this.showAddDrug$ = this._store.select(reducer.getVisible);
this.showAddIndication$ = this._store.select(reducer.getVisible);
if (this.patient$.isEmpty) { this._router.navigateByUrl('dashboard/patient/add'); }
}
openAddPatient() { this._store.dispatch(new layout.LayoutActions.OpenAddPatientFormAction()); }
openAddDrug() { this._store.dispatch(new layout.LayoutActions.OpenAddDrugFormAction()); }
openAddIndication() { this._store.dispatch(new layout.LayoutActions.OpenAddIndicationFormAction()); }
}
当访问仪表板容器时,我在控制台上收到以下错误:
RROR TypeError: Cannot read property 'patient' of undefined
at getPatient (patient.reducer.ts:55)
任何人都可以帮助解决此错误吗? 感谢。