In angular universal project in ssr mode after successfully importing transferred state into store, next dispatched action @ngrx/store/update-reducers
wipes the store. Actually there are multiple @ngrx/store/update-reducers
actions fired (>10).
Inspecting in @ngrx/store-devtools (chrome extension) shows incorrectly that store after @ngrx/store/update-reducers
is still filled with data but it's not true, I see that previously loaded data in cmp disappears after a quick moment (when this mentioned action fires).
It only happens in ssr mode, although multiple @ngrx/store/update-reducers
are still present in @ngrx/store-devtools in classic ng serve
.
deps: angular 5.2.7, @ngrx/{store,effects,store-devtools,router-store} 5.2.0, chrome 66
Usually @ngrx/store/update-reducers
adds reducers from lazy loaded feature modules. Thus I assume that in your case multiple feature modules are lazy loaded.
What most probably happens is that transferred state is set before reducers for lazy loaded modules are added. By default ngrx will clear all parts of state that have no reducers assigned (this is done in combineReducers
function which runs on every action dispatched).
Possible solutions:
1. Assign default reducers in root module for feature modules
StoreModule.forRoot(initialReducerMap, { initialState: getInitialState })
export function defaultReducer(state) { return state; }
export const initialReducerMap = {
// this will make sure `feature1` and `feature2` parts are not cleared on next action
feature1: defaultReducer,
feature2: defaultReducer
} as ActionReducerMap<ApplicationState>;
export function getInitialState() {
return {
feature1: feature1.initialState,
feature2: feature2.initialState
};
}
More info in this blog post
2. Manually set transferred state parts for lazy loaded modules
import { ActionReducer, UPDATE } from "@ngrx/store";
let transferedState: any;
export function stateSetter(reducer: ActionReducer<any>): ActionReducer<any> {
return function(state: any, action: any) {
if (action.type === 'SET_ROOT_STATE') {
transferedState = action.payload;
return action.payload;
}
// on "update-reducers" set their initial transfered state
if (action.type === UPDATE && transferedState && action.features) {
const features: string[] = (action as any).features;
const newState = { ...state };
for (const feature of features) {
newState[feature] = newState[feature] || transferedState[feature];
}
return reducer(newState, action);
}
return reducer(state, action);
};
}
Other
Refer to this github issue