angularngrxngrx-storengrx-selectors

`selector` return the value on page refresh, `onInit` value shows as undefined


I am triggering a dispatch on onInit of the shell component, but getting the value as undefined. in case if i refresh the page, the value return properly from selector. do not know how to fix this. not getting any error too.. users part of actions works fine.

here is the action:

import { createAction, props } from "@ngrx/store";
import { PropUsers, PropUser } from "./reducer";

export const userActions = {
    GET_USERS: '[users] Get Users',
    GET_USERS_SUCESS: '[users] Get Users Success',
    GET_USERS_FAILURE: '[users] Get Users Failure',

    GET_PROFILE: '[users] Get Users',
    GET_PROFILE_SUCESS: '[users] Get Users Success',
    GET_PROFLE_FAILURE: '[users] Get Users Failure',
}

export const actionGetUsers = createAction(userActions.GET_USERS);
export const actionGetUsersSuccess = createAction(userActions.GET_USERS_SUCESS, props<{ users: PropUsers[] }>());
export const actionGetUsersFailure = createAction(userActions.GET_USERS_FAILURE, props<{ error: string }>());

export const actionGetProfile = createAction(userActions.GET_PROFILE);
export const actionGetProfileSuccess = createAction(userActions.GET_PROFILE_SUCESS, props<{ user: PropUser }>());
export const actionGetProfileFailure = createAction(userActions.GET_PROFLE_FAILURE, props<{ error: string }>());

selector:

import { createSelector, createFeatureSelector } from '@ngrx/store';
const usersSelector = createFeatureSelector<any>("store");

export const selectUsers = createSelector(usersSelector, (state) => {
    return state.reducerUser.users;
})
export const selectProfile = createSelector(usersSelector, (state) => {
    console.log('state', state.reducerUser.profile);
    return state.reducerUser.profile;
})

shell component:

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { Store, select } from "@ngrx/store";
import { Observable } from 'rxjs';
import { map } from "rxjs/operators";
import { PropUser } from '../../store/reducer';
import { actionGetProfile } from './../../store/actions';
import { selectProfile } from "./../../store/selectors";

@Component({
  selector: 'app-shell-user-profile',
  templateUrl: './shell-user-profile.component.html',
  styleUrls: ['./shell-user-profile.component.scss']
})
export class ShellUserProfileComponent implements OnInit {

  @Output() userProfile$: Observable<PropUser> = new EventEmitter<PropUser>();
  @Output() standClass: string;

  constructor(private readonly store: Store) {
    this.standClass = '12th';
  }

  ngOnInit(): void {
    this.store.dispatch(actionGetProfile());
    this.store.select(selectProfile).subscribe(data => console.log('data', data)); //undefined until refresh the page
  }

}

Solution

  • You should use different string values for your actions.

    GET_USERS: '[users] Get Users',
    

    is the same as

    GET_PROFILE: '[users] Get Users',
    

    So even though it seems like you are triggering a different action (because you use another symbol), you are actually triggering the same action that fetches the users.

    Every one of your actions should have a different string value. Try this instead:

    GET_PROFILE: '[users] Get Profile',
    GET_PROFILE_SUCESS: '[users] Get Profile Success',
    GET_PROFLE_FAILURE: '[users] Get Profile Failure',