Ngrx state undefined

I am trying to encapsulate the state of ngrx in a common service class in order to abstract implementation details from my components.

An example of a class of service that is registered in my application .module.ts providers

 @Injectable() export class PatientService { state: Observable<PatientState>; constructor( private store: Store<AppState>, ) { this.state = store.select<PatientState>('patients'); } } 

I checked my actions, the reducer and effects work as expected, however, when I subscribe to the service status in the component, it returns undefined .

An example of a component subscription using a shared service:

 @Component({ ... }) export class DashboardComponent implements OnInit { constructor( private patientService: PatientService, ) {} ngOnInit(): void { // dispatches action to load patient from API this.patientService.loadPatient(); this.patientService.state.subscribe(patientState => { console.log('patientState', patientState); // Does not work. Logs undefined. }); } } 

If I subscribe directly to the repository, it works as expected.

Example:

 @Component({ ... }) export class DashboardComponent implements OnInit { constructor( private patientActions: PatientActions, private store: Store<AppState>, ) {} ngOnInit(): void { this.store.dispatch(this.patientActions.loadPatient()); this.store.select<PatientState>('patients').subscribe(patientState => { console.log('patientState', patientState); // Works as expected. }); } } 

What am I doing wrong?

+10
angular ngrx
source share
3 answers

I have implemented a similar use case. Your attempt is good, and it worked out like this:

 @Injectable() export class PatientService { // Define Observable patientState$: Observable<PatientState>; constructor(private store: Store<AppState>) { // Get data from the store this.patientState$ = store.select<PatientState>('patients'); } getState(): PatientState { // subscribe to it so i don't have to deal with observables in components let patientState: PatientState = null; this.patientState$.subscribe(ps => patientState = ps); return patientState; } } 

Now you can call this method from any component that you need:

 @Component({ ... }) export class DashboardComponent implements OnInit { patientState = new PatientState; constructor( private patientService: PatientService, ) {} ngOnInit(): void { // Simply get the Object from the store without dealing with observables this.patientState = this.patientService.getState(); } } 

I use $ at the end of the observables, so every time I touch a variable, I know whether it is observable or not, so I'm not confused.

0
source share

I think you are missing this link,

 this.state = store.select<PatientState>('patients'); 

should be

 this.state = this.store.select<PatientState>('patients'); 
0
source share

I solved this by following Mergasov’s advice and setting the default condition:

I had a similar problem: when a component subscribes to state, it always gets state === undefined . This was very confusing for me, but in the end I found that the corresponding reducer is not implemented magic code: default: return state;

Here's what it looks like in the context of a larger reducer.ts :

  export function reducer(state: EntityState= initialEntityState, action: actions.EntityAction) { switch (action.type) { case actions.CREATE_ENTITY_SUCCESS: case actions.UPDATE_ENTITY_SUCCESS: { const EntityDetails = action.payload; const entities = { ...state.entities, [Entitydetails.Id]: EntityDetails, }; return { ...state, error: null, entities, }; } default : { return state; } } } 

Previously, my code did not have a default condition and returned undefined due to this fact. adding a default condition for the gearbox solved the problem.

0
source share

All Articles