angularreduxangular-redux

Angular 4 Redux select issue (basic)


I am still in the early stages of learning Angular 4 and Redux. I have a component that gets information from the store. It works fine IN THE VIEW. But when I try to access the same information from within the component, I get an object instead of the value.

Here is my component:

import { Component } from '@angular/core';
import { NgRedux, select } from 'ng2-redux'; 
import { AppState } from '../../reducers/reducer';
import { QuizService } from '../../services/quiz.service';  
import { clearQuiz } from '../../actions/actions'; 

@Component({ 
    selector: 'quiz', 
    templateUrl: './quiz.component.html', 
    styleUrls: ['./quiz.component.css']
})

export class Quiz {
    constructor(private ngRedux: NgRedux<AppState>, private service: QuizService) {}

    @select('currentQuiz') currentQuiz;
    @select('quizLength') quizLength; 
    @select('sessionId') sessionId; 

    handleClose() {
        console.log("CLOSE", this.sessionId )
        this.service.deleteSession(this.sessionId)
            .subscribe(res => {
                this.ngRedux.dispatch(clearQuiz())
            })
            , error => {
                console.error(error); 
            }
    }
}

The "console.log("CLOSE", this.sessionId )" line does not return the value stored in the store. Instead, I get this:

CLOSE AnonymousSubject {_isScalar: false, observers: Array(0), closed: false, isStopped: false, hasError: false, …}

How do you get the data off of these objects within the class? In the view, if I add "| async" after the value, they show up. But I can not get the values from within the actual component class. Help!


Solution

  • You have to subscribe to the selected slices of the state, because when you @select from the store you do not get a value but an Observable. That's why you have to use the async pipe in your template. It automatically does the subscribing for you.

    You could for example subscribe in the OnInit Hook and assign it to a field. It's good practice to give fields the suffix $ if they are Observables. I've assumed that you have an interface IQuiz for the data model of currentQuiz. If the variable name is the same as the store property (ignoring $), you can omit it with the @select:

    @select() currentQuiz$: Observable<IQuiz>;
    currentQuiz: IQuiz;
    
    // ...
    
    ngOnInit() {
      this.currentQuiz$.subscribe(currentQuiz => this.currentQuiz = currentQuiz)
    }
    

    When your store is updated, this.currentQuiz will automatically be reassigned.