Ionic 3 - Ngrx Feature State is empty

#1

Hi all,

I finished an Ionic v3 app that has a lot of lazy loaded pages.

The problem is that when I build the app with the prod flag, all the state belonging to lazy loaded pages is empty. If I move those same reducers to the main store everything works fine. I already shipped an angular 5 application with lazy loaded modules + ngrx and everything works fine.

Does anyone has a solution besides transfering all the reducers to the main store?

#2

Something’s wrong in your code. You do not need lazily loaded state slices to be in your global state. Defeats the purpose. Do you define a lazily loaded store?

#3

I do know that…thats the reason why I opened this topic. Everything works fine in dev mode, it’s only when AOT is enabled that the lazy loaded reducers are empty

#4

I can’t say anything specific if you don’t share code. Whatever you’re doing, it breaks in ngc/ngo. It might be a really simple fix, if it works in dev mode. If you aren’t comfortable posting code, take a look at this thread, to see what might be causing your code to break. What does --prod flag do exactly?

#5

I can post code no problem. So this is my main store. The “cartoons” reducer is working now, but it is originally a lazy loaded page with it’s own reducer.

export interface IAppState {
    notifications: fromNotifications.NotificationsState,
    menu: fromMenu.State,
    cartoons: fromCartoon.State
}

export const reducers: ActionReducerMap<IAppState> = {
    notifications: fromNotifications.reducer,
    menu: fromMenu.reducer,
    cartoons: fromCartoon.cartoonsReducer
};


export function logger(reducer: ActionReducer<IAppState>): ActionReducer<any, any> {
    return function (state: IAppState, action: any): IAppState {
        console.log('state', state);
        console.log('action', action);

        return reducer(state, action);
    };
}

export const metaReducers: MetaReducer<IAppState>[] = !environment.production
    ? [logger/* , storeFreeze, localStorageSyncReducer */]
    : [/* localStorageSyncReducer */];

And this is the original lazy loaded cartoon reducer:

export interface CartoonState {
    cartoons: fromCartoons.State;
}

export interface State extends fromRoot.IAppState {
    cartoons: CartoonState;
}

export const reducers: ActionReducerMap<CartoonState> = {
    cartoons: fromCartoons.cartoonsReducer
};

export const selectCartoonState = createFeatureSelector<CartoonState>(CommonEntities.CARTOONS.toLowerCase());

export const getCartoonState = createSelector(
    selectCartoonState,
    (state: CartoonState) => state.cartoons.obj ? state.cartoons.obj.items : null
)

export const isLoading = createSelector(
    selectCartoonState,
    (state: CartoonState) => state.cartoons.loading
)

export const getCartoonPage = createSelector(
    selectCartoonState,
    (state: CartoonState) => state.cartoons.pageNumber
)

export const isFinished = createSelector(
    selectCartoonState,
    (state: CartoonState) => state.cartoons.finishedPages
)

#6

This is in ngrx 4?

…post must be 20 characters…

#7

It’s ngrx v5 with angular v5

#8

In my own code, I have lazily loaded features modules. Some of those features have their own stores. Let’s say there’s a feature Foo. I don’t make the Foo store extend the fromRoot store. Instead, I have what you could consider a second root, that only exists while the Foo feature is loaded. Store<fromFoo> instead of Store<fromRoot> so to speak.

#9

And you initializite in the feature module with StoreModule.forFeature right?

I will try that approach. But this approach is the same I used in my last Angular App and the same it is used in the Ngrx Example App

#10

I haven’t looked at that example for maybe 5 months, but it isn’t lazy loaded I don’t think. At least it didn’t use to be, and I don’t see loadChildren after looking now for 1 minute. At any rate, I’m not 100% sure of the best practice here, but I know my way works for my use case. I define a rootStore that I can call root actions on, if I need to do that in a lazily loaded page. And I define a more local store, the Foo store, with which I can perform the foo actions.

#11

loadChildren is from Angular Router, Ionic3 does not use Angular router. I don’t have this problem with an angular-only project. Just with Ionic and it’s lazy loaded pages.

And yes in that example the book module is lazy loaded.

#12

Maybe move to Ionic 4 then? Sidestep the problem completely.

#13

Ionic 4 is not even in the final version, I would have to rewrite a lot of code, and the app ships next week lol.

If there is no workaround I’ll keep the lazy loaded pages, but the reducers move to being eagerly loaded.