ngrx 商店 4 select 不工作
ngrx store 4 select not working
我整天都在努力让我的 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>
您的应用状态未正确建模。实际上有一个包含您的年龄的 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()));
}
}
请注意您的 AppState 中有“reducer”对象的原因是因为当您设置时这样做:StoreModule.forRoot({ reducer })
。它从 reducer 获取“reducer”名称。
换句话说,如果您执行类似 StoreModule.forRoot({ ageReducer })
的操作,那么您的应用状态将如下所示:
export interface AppState {
ageReducer: {
age: number
}
}
这是代码的工作版本:
另请注意,如果您使用的是 angular 异步管道,则无需在您的可观察对象上调用 .subscribe。异步管道句柄 subscription/unsubscription.
我整天都在努力让我的 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>
您的应用状态未正确建模。实际上有一个包含您的年龄的 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()));
}
}
请注意您的 AppState 中有“reducer”对象的原因是因为当您设置时这样做:StoreModule.forRoot({ reducer })
。它从 reducer 获取“reducer”名称。
换句话说,如果您执行类似 StoreModule.forRoot({ ageReducer })
的操作,那么您的应用状态将如下所示:
export interface AppState {
ageReducer: {
age: number
}
}
这是代码的工作版本:
另请注意,如果您使用的是 angular 异步管道,则无需在您的可观察对象上调用 .subscribe。异步管道句柄 subscription/unsubscription.