ngrx / store

RxJS powered state management for Angular applications, inspired by Redux
MIT License
3.9k stars 310 forks source link

Observable value undefined #454

Closed feischml closed 7 years ago

feischml commented 7 years ago

Hello,

I'm trying to make a simple example with ngrx but somehow don't get the wished result -> list items are undefined.

Here is my code:

  1. Action:

    ...
    export const GET_ASSOCIATIONS = '[Associations] Get Associations';
    export class GetAssotiationsAction implements Action{
      readonly type = GET_ASSOCIATIONS;
      constructor(public payload: Association[]) { }
    }
    ...
  2. Reducer:

    
    ...
    export interface AssociationState {
    associations: Association[];
    selectedAssotiation: Association;
    };

export const initialState: AssociationState = { associations: [], selectedAssotiation: null };

export function assotiationsReducer(state = initialState, action: AssociationsActions.Actions) { switch (action.type) { case AssociationsActions.GET_ASSOCIATIONS: console.log(action.payload); //-> here I get the right results from the server: an array of objects return action.payload; default: return state; } ...


3. Service: AssociationService
```javascript
...
associations$: Observable<Array<Association>>;

constructor( private _http: Http, private _store: Store<AssociationState> ){
  this.associations$ = this._store.select('associations');
  console.log(this.associations$); //-> here I get a store Object. Shouldn't this be an observable?
}

getAssociationsDispatch(){
        var route = '/associations/associations';
        console.log("Calling action GET_ASSOCIATIONS");
        this._http.get(
                this.appConstants.getServerUrl() + route)
            .map( associations => associations.json())
            .map( payload => ({ type: associationActions.GET_ASSOCIATIONS, payload: payload}) )
            .subscribe( action => this._store.dispatch(action));
        // -> in the reducer, the payload has the array of objects returned by the server - see in
        // reducer: console.log(action.payload)
}
  1. Component:
    
    ...
    associations$: Observable<Array<Association>>;

constructor(private _associationsService: AssociationService){ }

ngOnInit(){ this._associationsService.getAssociationsDispatch(); this.associations$ = this._associationsService.associations$;

    // -> this.associations$ is undefined all the time

}


Since ``` this.associations$ ``` is undefined, no values will be rendered in the .html template
``` <association-list [associations]="associations$ | async"></association-list>```

I also tried to return the following in the reducer, but with no luck:
```javascript
switch (action.type) {
        case AssociationsActions.GET_ASSOCIATIONS:
            console.log(action.payload);
            return Object.assign( state, {associations: action.payload});

        default: 
            return state;
}

Any ideas what could be missing?

Thank you, Laszlo

criticalbh commented 7 years ago

Hello @feischml, instead of return Object.assign( state, {associations: action.payload}); try return Object.assign({}, state, {associations: action.payload});. This will create new object and wont mutate state. Also I would suggest to take a look and ngrx example app and usage of effects.

feischml commented 7 years ago

Hi @criticalbh, I tried also this, but the same result. I didn't introduce the effects for the sake of simplicity.

feischml commented 7 years ago

Also tried the following without success:

this.associations$ = this._store.select('associations');
...
getAssociationsDispatch(){
        var route = '/associations/associations';
        console.log("Calling action GET_ASSOCIATIONS");
        this._http.get(
                this.appConstants.getServerUrl() + route)
            .map( associations => associations.json())
            .map( payload => ({ type: associationActions.GET_ASSOCIATIONS, payload: payload}) )
            .subscribe( action => this._store.dispatch(action));

        console.log(this.associations$);
// here in the Store the desired values are there, see screenshot: associations: Array (2) 
screen shot 2017-07-30 at 18 23 56
         this.associations$.subscribe(res => console.log(res));
// here the result is: undefined - but why?

}
feischml commented 7 years ago

Hi, solved with:

this.associations$ = this._store.select(
            (state:AppState) => {
                return state.associations
            }
        ).select('associations');
luchillo17 commented 7 years ago

What the? can you chain select calls?