如何使用 ngrx-store 调入正确的商店 'collection'?
How do I call into correct store 'collection' with ngrx-store?
我有两个数据集(示例应用程序 - 尝试学习 ngrx)计数器和 urls。我可以在各自的组件中正确地拉取和显示 2 个商店中的每一个。使用 ngrx-store 中的计数器示例,我还可以递增和递减计数器。我为 urls 添加了一个减速器,现在它在动作开关中只有一个默认值。
问题:当我递增计数器时,也会触发 url 默认操作。我没有正确地在 1 个减速机上只选择 1 个动作。我怎么做?
可能的答案?:我认为每个 reducer 的动作都需要不同?即,'counter-increment' 和 'url-increment' 与使用 'increment' 的两个减速器相比?或者还有其他方法吗?
我是 ngrx 和 rxjs 的新手,所以 simplest/most 直接代码会有所帮助。
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import 'rxjs/Rx';
import '@ngrx/core';
import { Store, StoreModule } from '@ngrx/store';
import { AppComponent } from './components/app.component';
import { UrlListComponent, UrlItemComponent, ListComponent, ListItemComponent, CounterComponent } from './components/index'
import { counterReducer, urlReducer} from './reducers/index';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
StoreModule.provideStore({counter: counterReducer, urls: urlReducer})
],
declarations: [ AppComponent, UrlItemComponent, UrlListComponent, ListComponent, ListItemComponent, CounterComponent],
bootstrap: [ AppComponent]
})
export class AppModule {
constructor(){console.log("AppModule");}
}
// app.component.ts
import { Injectable, Component, Output, Input, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { HttpModule } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Store } from '@ngrx/store';
import { INCREMENT, DECREMENT, RESET, Url } from '../reducers/index';
import { ListComponent, UrlListComponent, CounterComponent} from './index'
export interface AppState {
counter: number;
urls : Url[]
}
@Component({
moduleId: module.id, //system js variable name for relative path
selector: 'my-app',
template: `
<counter-comp [counter]="counter" ></counter-comp>
<url-list [urls]="urls"></url-list>
<list [innerArray]="myarray"></list>
`,
providers: [],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
counter: number;
urls: Url[];
myarray: number[] = [];
constructor(private store: Store<AppState>){
console.log('AppComponent constructor');
this.store.select(state => state.counter)
.subscribe(data => this.counter = data);
this.store.select(state => state.urls)
.subscribe(data => this.onUrlsEmitted(data));
this.myarray.push(1);
this.myarray.push(2);
this.myarray.push(3);
}
ngOnInit() {
console.log('AppComponent ngOnInit');
}
// executed once user data arrives from the store
public onUrlsEmitted(data:Url[]){
console.log('AppComponent onUrlsEmitted');
this.urls = data;
if(!data || !data.length){
console.log("no url data arrived");
}
}
}
// counter.component.ts
import { Component, Input } from '@angular/core';
import { Url, AppState, INCREMENT, DECREMENT, RESET } from '../reducers/index';
import { Store } from '@ngrx/store';
@Component({
selector: 'counter-comp',
template: `
<div class='counter'>
<div>Current Count: {{ counter }}</div>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset Counter</button>
</div>
`
,
styles:[`
div { width: 100%; }
.counter { background-color: #99bbff; }
`]
})
export class CounterComponent {
@Input() counter: number;
constructor(private store: Store<AppState>){
}
increment(){
console.log("counter.component.ts increment");
this.store.dispatch({ type: INCREMENT });
}
decrement(){
console.log("counter.component.ts decrement");
this.store.dispatch({ type: DECREMENT });
}
reset(){
console.log("counter.component.ts reset");
this.store.dispatch({ type: RESET });
}
ngOnInit() {
console.log('CounterComponent input: ' + this.counter);
}
}
// counter.ts
import { ActionReducer, Action } from '@ngrx/store';
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET';
export const counterReducer: ActionReducer<number> = (state: number = 0, action: Action) => {
console.log("counterReducer action.type " + action.type);
console.log(JSON.stringify(state));
switch (action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
case RESET:
return 0;
default:
console.log("counterReducer default");
return state;
}
}
// url.ts
import { ActionReducer, Action } from '@ngrx/store';
//export const INCREMENT = 'INCREMENT';
//export const DECREMENT = 'DECREMENT';
//export const RESET = 'RESET';
export interface Url{
id: number;
name: string;
}
let initialState = function(){
return [{id:1, name:"Dina"},{id:2, name:"Wayne"},{id:3,name:"kids"}];
}
export const urlReducer: ActionReducer<Url[]> = (state: Url[] = initialState(), action: Action) => {
console.log("urlReducer action.type " + action.type);
console.log(JSON.stringify(state));
switch (action.type) {
default:
console.log("urlReducer default");
console.log(state);
return state;
}
}
您应该添加 distinctUntilChanged
运算符。
this.store.select(state => state.urls).distinctUntilChanged().subscribe(data => this.onUrlsEmitted(data))
我有两个数据集(示例应用程序 - 尝试学习 ngrx)计数器和 urls。我可以在各自的组件中正确地拉取和显示 2 个商店中的每一个。使用 ngrx-store 中的计数器示例,我还可以递增和递减计数器。我为 urls 添加了一个减速器,现在它在动作开关中只有一个默认值。
问题:当我递增计数器时,也会触发 url 默认操作。我没有正确地在 1 个减速机上只选择 1 个动作。我怎么做?
可能的答案?:我认为每个 reducer 的动作都需要不同?即,'counter-increment' 和 'url-increment' 与使用 'increment' 的两个减速器相比?或者还有其他方法吗?
我是 ngrx 和 rxjs 的新手,所以 simplest/most 直接代码会有所帮助。
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import 'rxjs/Rx';
import '@ngrx/core';
import { Store, StoreModule } from '@ngrx/store';
import { AppComponent } from './components/app.component';
import { UrlListComponent, UrlItemComponent, ListComponent, ListItemComponent, CounterComponent } from './components/index'
import { counterReducer, urlReducer} from './reducers/index';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
StoreModule.provideStore({counter: counterReducer, urls: urlReducer})
],
declarations: [ AppComponent, UrlItemComponent, UrlListComponent, ListComponent, ListItemComponent, CounterComponent],
bootstrap: [ AppComponent]
})
export class AppModule {
constructor(){console.log("AppModule");}
}
// app.component.ts
import { Injectable, Component, Output, Input, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { HttpModule } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Store } from '@ngrx/store';
import { INCREMENT, DECREMENT, RESET, Url } from '../reducers/index';
import { ListComponent, UrlListComponent, CounterComponent} from './index'
export interface AppState {
counter: number;
urls : Url[]
}
@Component({
moduleId: module.id, //system js variable name for relative path
selector: 'my-app',
template: `
<counter-comp [counter]="counter" ></counter-comp>
<url-list [urls]="urls"></url-list>
<list [innerArray]="myarray"></list>
`,
providers: [],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
counter: number;
urls: Url[];
myarray: number[] = [];
constructor(private store: Store<AppState>){
console.log('AppComponent constructor');
this.store.select(state => state.counter)
.subscribe(data => this.counter = data);
this.store.select(state => state.urls)
.subscribe(data => this.onUrlsEmitted(data));
this.myarray.push(1);
this.myarray.push(2);
this.myarray.push(3);
}
ngOnInit() {
console.log('AppComponent ngOnInit');
}
// executed once user data arrives from the store
public onUrlsEmitted(data:Url[]){
console.log('AppComponent onUrlsEmitted');
this.urls = data;
if(!data || !data.length){
console.log("no url data arrived");
}
}
}
// counter.component.ts
import { Component, Input } from '@angular/core';
import { Url, AppState, INCREMENT, DECREMENT, RESET } from '../reducers/index';
import { Store } from '@ngrx/store';
@Component({
selector: 'counter-comp',
template: `
<div class='counter'>
<div>Current Count: {{ counter }}</div>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset Counter</button>
</div>
`
,
styles:[`
div { width: 100%; }
.counter { background-color: #99bbff; }
`]
})
export class CounterComponent {
@Input() counter: number;
constructor(private store: Store<AppState>){
}
increment(){
console.log("counter.component.ts increment");
this.store.dispatch({ type: INCREMENT });
}
decrement(){
console.log("counter.component.ts decrement");
this.store.dispatch({ type: DECREMENT });
}
reset(){
console.log("counter.component.ts reset");
this.store.dispatch({ type: RESET });
}
ngOnInit() {
console.log('CounterComponent input: ' + this.counter);
}
}
// counter.ts
import { ActionReducer, Action } from '@ngrx/store';
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET';
export const counterReducer: ActionReducer<number> = (state: number = 0, action: Action) => {
console.log("counterReducer action.type " + action.type);
console.log(JSON.stringify(state));
switch (action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
case RESET:
return 0;
default:
console.log("counterReducer default");
return state;
}
}
// url.ts
import { ActionReducer, Action } from '@ngrx/store';
//export const INCREMENT = 'INCREMENT';
//export const DECREMENT = 'DECREMENT';
//export const RESET = 'RESET';
export interface Url{
id: number;
name: string;
}
let initialState = function(){
return [{id:1, name:"Dina"},{id:2, name:"Wayne"},{id:3,name:"kids"}];
}
export const urlReducer: ActionReducer<Url[]> = (state: Url[] = initialState(), action: Action) => {
console.log("urlReducer action.type " + action.type);
console.log(JSON.stringify(state));
switch (action.type) {
default:
console.log("urlReducer default");
console.log(state);
return state;
}
}
您应该添加 distinctUntilChanged
运算符。
this.store.select(state => state.urls).distinctUntilChanged().subscribe(data => this.onUrlsEmitted(data))