Reputation: 3636
I'm using ngrx/store in my app and I'm having trouble saving an array. My array is set to empty at startup with:
export interface AppState{
customObjects: Array<CustomObject>;
};
export const initialState: AppState = {
customObjects: []
};
and I am trying to manually feed it an array of two CustomObjects using the following function:
loadCustomObjects() {
let initialItems: CustomObject[] = [
{
directoryName: "d_name_1",
brokenLinks: 0,
},
{
directoryName: "d_name_2",
brokenLinks: 0,
}
];
this.appStore.dispatch({ type: LOAD_CUSTOM_OBJECTS, payload: initialItems });
}
Calling this function dispatches a call to my reducer function:
export const mainReducer: ActionReducer = (state: AppState, action: Action) => {
if (typeof state == 'undefined') {
state = initialState;
}
switch (action.type) {
case LOAD_CUSTOM_OBJECTS:
return Object.assign({}, action.payload)
default: {
return state;
}
}
}
This all seems fine, but my main app component's array does not get the two objects. If I manually set the default state to have those two CustomObjects, then it works (I can't do this since I need to be able to update the array whenever I want). My HomeComponent uses:
customObjects$ Observable<Array<CustomObject>>;
constructor(private appStore: Store<AppState>) {
appstore.select('mainReducer')
.subscribe((data: AppState) => {
if (typeof data != 'undefined') {
this.customObjects$ = Observable.of(data.customObjects);
}
});
}
I've analyzed my objects and I expect to see 'this.customObjects$' end up being an array of two CustomObjects. Instead, it is a ScalarOservable:
ScalarObservable {_isScalar: true, value: undefined, scheduler: null}, etc. etc.
Note - I'm not sure if I need to, but I have included ChangeDetectionStrategy.onPush in my home component's @Component section. I've also made sure to use
StoreModule.provideStore({ mainReducer })
in my app.module class.
Does anyone know what I'm doing wrong and why 'this.customObjects$' is not a two object array? I'm new to ngrx/store - I get the feeling there is an issue with the way my reducer function is setting the array but I'm not sure.
Upvotes: 4
Views: 2182
Reputation: 2131
I was able to get it to work with this code:
Store related code:
export interface CustomObject {
directoryName: string;
brokenLinks: number;
}
export interface AppState {
Main: CustomObject[];
};
export function MainReducer(state: CustomObject[] = [], action: Action) {
switch (action.type) {
case LOAD_CUSTOM_OBJECTS:
return Object.assign({}, action.payload);
default: {
return state;
}
}
}
const reducers = {
Main: MainReducer
};
Component/Service to dispatch/listen to store
customObjects: CustomObject[];
constructor(private appStore: Store<AppState>) {
appStore.select(store => store.Main)
.subscribe(objs => {
this.customObjects = objs;
console.log(this.customObjects);
})
}
loadCustomObjects() {
let initialItems: CustomObject[] = [
{
directoryName: "d_name_1",
brokenLinks: 0,
},
{
directoryName: "d_name_2",
brokenLinks: 0,
}
];
this.appStore.dispatch({ type: LOAD_CUSTOM_OBJECTS, payload: initialItems });
}
Async pipe version:
customObjects$: Observable<CustomObject[]>;
constructor(private appStore: Store<AppState>) {
this.customObjects$ = appStore.select(store => store.Main);
}
loadCustomObjects() {
let initialItems: CustomObject[] = [
{
directoryName: "d_name_1",
brokenLinks: 0,
},
{
directoryName: "d_name_2",
brokenLinks: 0,
}
];
this.appStore.dispatch({ type: LOAD_CUSTOM_OBJECTS, payload: initialItems });
}
<div *ngFor="let customObj of customObjects$ | async"></div>
Upvotes: 1