ngrx store 4选择不工作

时间:2017-08-15 21:49:31

标签: angular ngrx-store-4.0

我整天都在努力让我的Angular应用程序与ngrx / store 4一起工作。经过多次不成功的工作,我决定创建一个新的绝对最小应用程序来检查我是否还有其他问题。但最小的应用程序根本不起作用:(

在Chrome Redux devtools中我可以看到,商店已正确更新。但UI未更新。此外,app.component.ts(this.age$.subscribe(console.log))中的日志语句永远不会执行。我真的不知道我错过了什么。

以下是相关代码。

的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>

2 个答案:

答案 0 :(得分:8)

您的应用状态未正确建模。实际上有一个包含你年龄的reducer对象。以下是我为使应用有效所做的更改:

在state.ts

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

在应用程序组件中:

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()));
  }
}

请注意您拥有&#34; reducer&#34; AppState中的对象是因为当你设置这样做时:StoreModule.forRoot({reducer})。它得到了减速机&#34;减速机的名称。

换句话说,如果您执行类似StoreModule.forRoot({ageReducer})的操作,那么您的应用状态将如下所示:

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

这是代码的工作版本:

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

答案 1 :(得分:3)

另请注意,如果您使用的是角度异步管道,则无需在您的observable上调用.subscribe。异步管道处理订阅/取消订阅。