Do you have a hunch about what are we missing to properly combine child and parent?
josoroma-zz opened this issue · 1 comments
josoroma-zz commented
Looks like parent
reducer is not properly combined or missing:
parent/components.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { ParentActions } from './actions';
import { StoreWithParent, parentStoreFactory } from './reducer';
@Component({
selector: 'parent-component',
templateUrl: './component.html',
providers: [{
provide: StoreWithParent,
useFactory: parentStoreFactory,
deps: [Store]
}]
})
export class ParentComponent {
counter: Observable<number>;
constructor(
private actions: ParentActions,
private store: StoreWithParent
) {
console.log('ParentComponent - store ===>', store);
this.counter = store.select(state => {
console.log('ParentComponent this.store.select - state ===>', state);
return state.parent.counter
});
}
decrement() {
this.store.dispatch(this.actions.decrement());
}
increment() {
this.store.dispatch(this.actions.increment());
}
reset() {
this.store.dispatch(this.actions.reset());
}
}
parent/reducer.ts
import { Store, ActionReducer, Action, combineReducers } from '@ngrx/store';
import { AppState, createNewRootReducer } from './../../reducers/index';
import { ParentActions } from './actions';
export interface ParentState {
counter: number;
}
const initialState: ParentState = {
counter: 0
};
export function parentReducer(state: ParentState = initialState, action: Action) {
switch (action.type) {
case ParentActions.DECREMENT:
return {
...state,
counter: state.counter - 1
};
case ParentActions.INCREMENT:
return {
...state,
counter: state.counter + 1
};
case ParentActions.RESET:
return {
...state,
counter: 0
};
default:
return state;
}
}
export interface AppStateWithParent extends AppState {
parent: ParentState;
}
export class StoreWithParent extends Store<AppStateWithParent> { }
export function parentStoreFactory(appStore: Store<AppState>) {
appStore.replaceReducer(createNewRootReducer({ parent: parentReducer }));
return appStore;
}
parent/child/component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { ChildActions } from './actions';
import { StoreWithChild, childStoreFactory } from './reducer';
@Component({
selector: 'child-component',
templateUrl: './component.html',
providers: [{
provide: StoreWithChild,
useFactory: childStoreFactory,
deps: [Store]
}]
})
export class ChildComponent {
counter: Observable<number>;
constructor(
private actions: ChildActions,
private store: StoreWithChild
) {
console.log('ChildComponent - store ===>', store);
this.counter = store.select(state => {
console.log('ChildComponent this.store.select - state ===>', state);
return state.child.counter
});
}
decrement() {
this.store.dispatch(this.actions.decrement());
}
increment() {
this.store.dispatch(this.actions.increment());
}
reset() {
this.store.dispatch(this.actions.reset());
}
}
parent/child/reducer.ts
import { Store, ActionReducer, Action, combineReducers } from '@ngrx/store';
import { AppState, createNewRootReducer } from './../../../reducers/index';
import { ChildActions } from './actions';
export interface ChildState {
counter: number;
}
const initialState: ChildState = {
counter: 0
};
export function childReducer(state: ChildState = initialState, action: Action) {
switch (action.type) {
case ChildActions.DECREMENT:
return {
...state,
counter: state.counter - 1
};
case ChildActions.INCREMENT:
return {
...state,
counter: state.counter + 1
};
case ChildActions.RESET:
return {
...state,
counter: 0
};
default:
return state;
}
}
export interface AppStateWithChild extends AppState {
child: ChildState;
}
export class StoreWithChild extends Store<AppStateWithChild> { }
export function childStoreFactory(appStore: Store<AppState>) {
appStore.replaceReducer(createNewRootReducer({ child: childReducer }));
return appStore;
}
Thanks in advance!
josoroma-zz commented
I'm glad, I finally did it :)
Import the ChildModule
in the ParentModule
:
@NgModule({
imports: [
...
ChildModule
]
...
})
Manage the childReducer
directly from the parentStoreFactory
:
export const parentStoreFactory = (appStore: Store<AppState>) => {
appStore.replaceReducer(
createNewRootReducer({
parent: parentReducer,
child: childReducer
})
);
Dispatch a Parent Action from the ChildComponent
:
...
reset() {
this.store.dispatch(this.childActions.reset());
}
incrementParent() {
this.store.dispatch(this.parentActions.increment());
}
...