ngRx Store - Reducer returns undefined - store.select() is undefined

1.9k Views Asked by At

it's my first time working with ngRx Store and I implemented my first effect..

What is working fine:

  • communication with backend
  • actions are being executed in backend (delete, add, get)
  • payload is getting to the reducer from effects (logged it to be sure)

So my problem is that I can not get Data from my reducer. If I select the data from the store in my component, I get undefined data in the component. I tapped the data in the effects and the data is definietly passed. Also logged the data in the reducer - it is there. But when it is returned, it returns undefined. ReDux Devtools logs everything fine. And last but not least.. the state is not updated, even with fixed values, like a boolean with true/false for loading.

Le Code:

// Where I get undefined

export class ProfileComponent implements OnInit {

  user: any;
  items$: Observable<Product[]>;
  loading$: Observable<boolean>;
  error$: Observable<Error>;
  newItem: Product = {id: 0, name:""};

  constructor(private keycloakService: KeycloakService, private store: Store<ProductState>, private productService: ProductService) { }

  ngOnInit(): void {
    this.productService.setToken(this.keycloakService.getToken());

    this.user = this.keycloakService.getUsername();

    this.items$ = this.store.select(store => store.list);
    this.loading$ = this.store.select( store => store.loading);
    this.error$ = this.store.select( store => store.error);

    this.store.dispatch(new LoadProduct());

    this.items$.subscribe(val => console.log(val));
    this.loading$.subscribe(val => console.log(val));
    this.error$.subscribe(val => console.log(val));
  }

// Reducer

export type Action = Products.All;

const initialState: ProductState = {
  list: [],
  loading: false,
  error: undefined
}

const newState = (state, newData) => {
  return Object.assign({}, state, newData);
}

export function reducer(state: ProductState = initialState, action: Action) : ProductState{
  console.log(action.type, state);

  switch (action.type) {
    case Products.LOAD_PRODUCT: return { ...state, loading: true};
    case Products.LOAD_PRODUCT_SUCCESS: return newState(state, {list: action.payload, loading: false, error: undefined});
    case Products.LOAD_PRODUCT_FAILURE: return { ...state, error: action.payload, loading: false};
    case Products.ADD_PRODUCT: return { ...state, loading: true};
    case Products.ADD_PRODUCT_SUCCESS: return { ...state, list: action.payload, loading: false};
    case Products.ADD_PRODUCT_FAILURE: return { ...state, error: action.payload, loading: false};
    case Products.REMOVE_PRODUCT: return { ...state, loading: true};
    case Products.REMOVE_PRODUCT_SUCCESS: return { ...state, list: state.list.filter(item => item.id !== action.payload), loading: false};
    case Products.REMOVE_PRODUCT_FAILURE: return { ...state, error: action.payload, loading: false};
    default: return state;
  }

I appreciate your help very much :)

1

There are 1 best solutions below

1
AliF50 On

You should use selector functions to get the data from the store: https://ngrx.io/guide/store/selectors

For a quick unblock, I bet .list, .loading, .error are undefined on state.

Try this to debug:

// see how the whole store looks like
this.store.subscribe(state => console.log({ state }));

And for you, I see it is related to products, so I bet it should be something like this:

this.items$ = this.store.select(store => store.products.list);
this.loading$ = this.store.select( store => store.products.loading);
this.error$ = this.store.select( store => store.products.error);