2017-08-15 1 views
3

Ich hatte den ganzen Tag zu kämpfen, um meine Angular-App mit ngrx/Geschäft 4 zu arbeiten. Nach vielen erfolglosen Stunden habe ich beschlossen, eine neue absolute minimale App zu erstellen, um zu überprüfen, ob ich vielleicht ein anderes Problem habe . Aber die minimale App funktioniert überhaupt nicht :(ngrx Geschäft 4 Wählen Sie nicht funktioniert

In den Chrome Redux Devtools kann ich sehen, dass der Laden ordnungsgemäß aktualisiert wird. Aber die Benutzeroberfläche wird nicht aktualisiert. Auch die Protokollanweisung in der app.component.ts (this.age$.subscribe(console.log)) wird nie ausgeführt. ich habe wirklich keine Ahnung, was ich vermisst.

Hier der entsprechende Code ist.

package.json

{ 
    "dependencies": { 
    "@angular/animations": "^4.2.4", 
    "@angular/common": "^4.2.4", 
    "@angular/compiler": "^4.2.4", 
    "@angular/core": "^4.2.4", 
    "@angular/forms": "^4.2.4", 
    "@angular/http": "^4.2.4", 
    "@angular/platform-browser": "^4.2.4", 
    "@angular/platform-browser-dynamic": "^4.2.4", 
    "@angular/router": "^4.2.4", 
    "@ngrx/store": "^4.0.2", 
    "@ngrx/store-devtools": "^4.0.0", 
    "rxjs": "^5.4.2", 
    "zone.js": "^0.8.14" 
    }, 
    "devDependencies": { 
    "@types/node": "^8.0.22", 
    "typescript": "^2.4.2" 
    } 
} 

app.module.ts

import { AppState } from './state'; 
import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { StoreModule } from '@ngrx/store'; 
import { StoreDevtoolsModule } from '@ngrx/store-devtools' 
import { reducer } from './reducer'; 

import { AppComponent } from './app.component'; 

@NgModule({ 
    declarations: [ 
    AppComponent 
    ], 
    imports: [ 
    BrowserModule, 
    StoreModule.forRoot({ reducer }), 
    StoreDevtoolsModule.instrument(), 
    ], 
    providers: [], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { } 

state.ts

export interface AppState { 
    age: number 
} 

export const INITIAL_STATE: AppState = { 
    age: 1 
} 

actions.ts

import { Action } from '@ngrx/store'; 

export const ACTION_TYPE = 'CHANGE_AGE_ACTION'; 

export class ChangeAgeAction implements Action { 
    readonly type: string = ACTION_TYPE; 

    constructor(public payload?: number) { 
    } 
} 

reducer.ts

import { ChangeAgeAction } from './actions'; 
import { Action } from '@ngrx/store'; 
import { AppState, INITIAL_STATE } from './state'; 
import { ACTION_TYPE } from './actions'; 

function changeName(state: AppState, action: ChangeAgeAction): AppState { 
    return { 
    age: action.payload 
    } 
} 

export function reducer(state: AppState = INITIAL_STATE, action: Action) { 
    switch (action.type) { 
    case ACTION_TYPE: 
     return changeName(state, action); 

    default: 
     return state; 
    } 
} 

app.component.ts

import { ChangeAgeAction } from './actions'; 
import { AppState } from './state'; 
import { Component } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import { Store } from '@ngrx/store'; 
import { map } from 'rxjs/operator/map'; 

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    age$: Observable<number>; 

    constructor(private store: Store<AppState>) { 
    this.age$ = this.store.select<number>(state => state.age); 
    this.age$.subscribe(console.log); 
    } 

    changeAge() { 
    this.store.dispatch(new ChangeAgeAction(Math.random())); 
    } 
} 

app.component.html

<h3>Age: {{ age$ | async }}</h3> 
<button (click)="changeAge()">Change Age</button> 

Antwort

4

Ihre App-Status nicht richtig modelliert wird. Es gibt tatsächlich ein Reducer-Objekt, das dein Alter enthält. Ist hier die Änderungen, die ich gemacht die App zu machen:

In state.ts

export interface AppState { 
    reducer: { 
    age: number 
    } 
} 

In App-Komponente:

export class AppComponent { 
    age$: Observable<number>; 

    constructor(private store: Store<AppState>) { 
    this.age$ = this.store.select<number>(state => state.reducer.age); 
    this.age$.subscribe(console.log); 
    } 

    changeAge() { 
    this.store.dispatch(new ChangeAgeAction(Math.random())); 
    } 
} 

Hinweis der Grund, dass Sie die "Reduzierer" bezwecken in Ihrem AppState ist, wenn Sie dies tun: StoreModule.forRoot ({Reducer}). Es erhält den "Reducer" -Namen von Reducer.

Mit anderen Worten, wenn Sie haben so etwas wie StoreModule.forRoot ({ageReducer}) dann Ihre App-Status würde wie folgt aussehen:

export interface AppState { 
    ageReducer: { 
    age: number 
    } 
} 

Hier ist eine Arbeitsversion des Code:

https://stackblitz.com/edit/angular-jxszwh

+0

Wow, das war der Trick!Vielen Dank! Ich schätze, ich würde noch ein paar Tage verschwenden, um das Problem zu finden. Meiner Meinung nach ist dies in der ngrx/store-Dokumentation nicht aussagekräftig genug erklärt. Ich würde niemals zu dem Schluss kommen, dass der Name des Reduzierers gleich dem Namen des Staates sein muss. –

+0

Ich stimme zu, das ist verwirrend. Ich bin selbst mehrmals darüber gestolpert. – seescode

0

Beachten Sie auch, wenn Sie die eckige asynchrone Pipe verwenden, müssen Sie .subscribe nicht auf Ihrer Observable aufrufen. Die asynchrone Pipe behandelt die An-/Abmeldung.

Verwandte Themen