Search code examples
angulartypescriptngrx-store

Why i receive store object instead my own object (PizzaState)?


I am try to create a pizzas$ object in type Observable<PizzaState> but i get a problem

I receive a store object instead PizzaState object and i don't understand why and how to fix it

this the object i get

Store {_isScalar: false, actionsObserver: ActionsSubject, reducerManager: ReducerManager, source: Store, operator: DistinctUntilChangedOperator}

I only tried to read my initialState from my store

my read component

import { Component, OnInit } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { ProductesState } from '../shared/models/productesState.model';
import { Observable } from 'rxjs';
import { PizzaState } from '../shared/models/pizzaState.model';
import * as fromPizzas from '../store/actions/pizzas.action'

@Component({
  selector: 'app-read',
  templateUrl: './read.component.html',
  styleUrls: ['./read.component.css']
})
export class ReadComponent implements OnInit {

  public pizzas$: Observable<PizzaState> = this.store.pipe(select('pizzas'));

  constructor(private store: Store<ProductesState>) { }

  ngOnInit() {
    console.log(this.pizzas$);
  }

my actions

import { Action, createAction, props } from '@ngrx/store';
import { Pizza } from 'src/app/shared/models/Pizza.model';


export const LoadPizzas = createAction('[Products] Load Pizzas')
export const LoadPizzasFail = createAction('[Products] Load Pizzas Fail', props<{ payload: Pizza[] }>())
export const LoadPizzasSuccess = createAction('[Products] Load Pizzas Success', props<{ payload: Pizza[] }>())

my reducer

import { PizzaState } from 'src/app/shared/models/pizzaState.model';
import * as fromPizzas from '../actions/pizzas.action'
import { createReducer, on } from '@ngrx/store';

export const initialState: PizzaState = {
    data: [],
    loaded: false,
    loading: false
}

export const reducer = createReducer<PizzaState>(
    initialState, on(
        fromPizzas.LoadPizzas, state => {
            return {
                ...state,
                loading: true
            }
        }
    ), on(
        fromPizzas.LoadPizzasSuccess, state => {
            return {
                ...state,
                loaded: true,
                loading: false
            }
        }
    ), on(
        fromPizzas.LoadPizzasFail, state => {
            return {
                ...state,
                loaded: false,
                loading: false
            }
        }
    )

)

reducer.index

import { reducer } from './pizzas.reducer';
import { ActionReducerMap } from '@ngrx/store';
import { ProductesState } from 'src/app/shared/models/productesState.model';

export const reducers: ActionReducerMap<ProductesState> = {
    pizzas: reducer
}

my module

import { reducers } from './store/reducers/index';

    StoreModule.forRoot({
      pizzas: reducers.pizzas
    })

my models

import { PizzaState } from './pizzaState.model';

export interface ProductesState {
    pizzas: PizzaState;
}

----------

import { Pizza } from './Pizza.model';

export interface PizzaState {
    data: Pizza[],
    loaded: boolean,
    loading: boolean
}

----------

export interface Pizza {
    id: number,
    name: string
}

if need more files i will glad to add , thank you for helping.


Solution

  • This is because you are logging your Observable instead of subscribing to it. NGRX uses an extended Observable called Store, so what you are seeing is absolutely correct.

    @Component({
      selector: 'app-read',
      templateUrl: './read.component.html',
      styleUrls: ['./read.component.css']
    })
    export class ReadComponent implements OnInit {
    
      public pizzas$: Observable<PizzaState> = this.store.pipe(select('pizzas'));
    
      constructor(private store: Store<ProductesState>) { }
    
      ngOnInit() {
        console.log(this.pizzas$);   // This logs your Observable, which holds your store value over time
    
        this.pizzas$.subscribe(currentPizzas => {
           // This function is called everytime your state changes + initial state
           console.log(currentPizzas); // This logs your current pizza state
        });
      }
    }
    

    Since you are refering this video over and over again, I'll explain the difference. In the video he is creating a Stream containing the cars in an Observable called cars$. He then uses that Observable only inside his template to show some data by using the async pipe like this <car-table [cars]="cars$ | async">. This async pipe takes care of subscribing and unsubscribing for you.