Reputation: 3880
I'm not new to Angular but I'm new to ngrx. I'm trying to get some values from my server and simply print them to the screen, I can see that the values are returning from the server after that the effect catches the action and do it's job:
but then my simple component doesn't show anything:
ProfileComponent.ts:
export class ProfileComponent implements OnInit {
network$= this.store.select(a=>a.NetworkInfo)
profiles$: Observable<Profile[]> = this.store.select(state => state.Profiles);
constructor(private store:Store<NetAlertState>) { }
ngOnInit() {
this.store.dispatch({ type: '[Profile Component] getAllProfiles' });
this.store.dispatch({ type: '[Profile Component] getNetworkInfo' });
}
}
profile.component.html:
<div *ngFor="let profile of profiles$ | async">
{{ profile.name }}
</div>
net-alert.actions.ts:
export const getAllProfiles = createAction('[Profile Component] getAllProfiles');
export const getNetworkInfo = createAction('[Profile Component] getNetworkInfo');
export const loadProfilesSuccess = createAction('[Profile Component] loadProfilesSuccess',props<{items:Profile[]}>());
export const loadNetworkInfoSuccess = createAction('[Profile Component] loadNetworkInfoSuccess', props<NetworkInfo>());
export const loadProfilesFailure = createAction('[Profile Component] loadProfilesFailure',props<String>());
export const loadNetworkInfoFailure = createAction('[Profile Component] loadNetworkInfoFailure',props<String>());
net-alert.reducer.ts
export const initialState: NetAlertState = {
Profiles:null,
NetworkInfo:null,
isLoading: false,
error: null
}
export const NetAlertReducer = createReducer(
initialState,
on(NetAlertActions.getAllProfiles, state => ({ ...state,isLoading:true ,error:null})),
on(NetAlertActions.loadProfilesSuccess, (state,profiles) => ({ Profiles:profiles,...state ,isLoading:false ,error:null})),
on(NetAlertActions.loadProfilesFailure, (state,err) => ({ ...state,isLoading:false ,error:err})),
on(NetAlertActions.getNetworkInfo, state => ({ ...state ,isLoading:true ,error:null})),
on(NetAlertActions.loadNetworkInfoSuccess, (state,res) => ({ ...state,NetworkInfo:res,isLoading:false ,error:null})),
on(NetAlertActions.loadNetworkInfoFailure, (state,err) => ({ ...state,isLoading:false ,error:err})),
);
export function reducer(state: NetAlertState | undefined, action: Action) {
return NetAlertReducer(state, action);
}
net-alert.effects.ts:
@Injectable()
export class NetAlertEffects {
loadProfiles$ = createEffect(() =>
this.actions$.pipe(
ofType('[Profile Component] getAllProfiles'),
mergeMap(() => this.dataService.getAllProfiles()
.pipe(
map(res => ({ type: '[Profile Component] loadProfilesSuccess', payload: res })),
catchError(() => of({ type: '[Profile Component] loadProfilesFailure' }))
)
)
)
);
constructor(
private actions$: Actions,
private dataService: DataService
) {}
}
net-alert.state.ts:
export interface NetAlertState {
isLoading: boolean;
error: any;
NetworkInfo: NetworkInfo;
Profiles: Profile[];
}
export interface Profile {
Mac: string;
NickName: string;
CreateDate: Date;
Sites?: any;
}
root-state.ts:
export interface AppStates {
netAlert: NetAlertState;
}
export const netAlertReducers: ActionReducerMap<AppStates> = {
netAlert: netAlertRerucers.reducer
};
app.module.ts:
@NgModule({
declarations: [
AppComponent,
ProfileContainerComponent,
ProfileComponent
],
imports: [
HttpClientModule,
BrowserModule,
AppRoutingModule,
StoreModule.forRoot(netAlertReducers),
EffectsModule.forRoot([NetAlertEffects]),
StoreDevtoolsModule.instrument({
maxAge: 25, // Retains last 25 states
logOnly: environment.production, // Restrict extension to log-only mode
}),
RootStoreModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
is anyone can tell me where is my mistake?
Thanks a lot!
Upvotes: 1
Views: 3188
Reputation: 20092
You should put your profiles$ in ngOnInit method like this
export class ProfileComponent implements OnInit {
network$: any;
profiles$: Observable<Profile[]>
constructor(private store:Store<NetAlertState>) { }
ngOnInit() {
this.store.dispatch({ type: '[Profile Component] getAllProfiles' });
this.store.dispatch({ type: '[Profile Component] getNetworkInfo' });
this.network$ = this.store.select(a=>a.NetworkInfo);
this.profiles$ = this.store.pipe(select(state => state.Profiles));
}
}
Also try to use pipe operator
Upvotes: 1
Reputation: 8002
I don't see a selector for selecting the "netAlert" state, upon which you build the other selectors, like so:
selectors.ts
import * as fromNetAlertState from "./state";
export const netAlertState = (state: State) => state.netAlert;
export const selectProfiles = createSelector(
netAlertState,
(state: fromNetAlertState.State) => state.Profiles
);
component.ts
profiles$: Observable<Profile[]>
ngOnInit() {
this.profiles$ = this.store.pipe(select(selectProfiles))
}
Upvotes: 1
Reputation: 3604
It won't work if you don't have a reducer to update your state from loadProfilesSuccess
action. Something like:
const myReducer = createReducer(
initialState, // type NetAlertState
on(from.loadProfilesSuccess, (state, action) => {
// return new state from action payload
}),
)
export function reducer(state: NetAlertState, action: Action) {
return myReducer(state, action);
}
You have actions but you never used them as well. You should use them everywhere:
ngOnInit() {
this.store.dispatch(getAllProfiles());
this.store.dispatch(getNetworkInfo());
}
loadProfiles$ = createEffect(() =>
this.actions$.pipe(
ofType(getAllProfiles),
mergeMap(() => this.dataService.getAllProfiles()
.pipe(
map(res => loadProfilesSuccess(res)),
catchError(() => of(loadProfilesFailure())
)
)
)
);
Upvotes: 1