I'm attempting to encapsulate my ngrx state in a shared service class to abstract the implementation details away from my components.
Example service class that is registered in my app.module.ts providers
@Injectable()
export class PatientService {
state: Observable<PatientState>;
constructor(
private store: Store<AppState>,
) {
this.state = store.select<PatientState>('patients');
}
}
I have verified my actions, reducer and effects are working as expected, however, when I subscribe to the service state in a component, it returns undefined
.
Example component subscription using the 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 store, 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?
NgRx is a framework for building reactive applications in Angular. NgRx is inspired by the Redux pattern - unifying the events in your application and deriving state using RxJS. At a high level, NgRx stores a single state and uses actions to express state changes.
NgRx is a popular solution in the Angular ecosystem if you are building complex web applications with sophisticated state management. Characteristics of the need for NgRx are many user interactions and multiple data sources. NgRx is a good choice, if: the state should be accessed by many components and services.
Where Does NgRx Store Data? NgRx stores the application state in an RxJS observable inside an Angular service called Store. At the same time, this service implements the Observable interface.
I solved this by following Mergasov's advice and set a default case condtion:
I had the similar issue: when a component subscribes to state it gets
state === undefined
always. It was very confused for me, but finally I've found corresponding reducer is not implemented magic code:default: return state;
Here's how that looks 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 was returning undefined
due to that fact. adding the default
condition to the reducer resolved the issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With