You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Server side rendering set up with state transfer as per #101 - server state is set on client with custom action (triggered by effect) on app init by meta reducer:
App includes lazy loaded modules which are loaded on server side and their state is also transferred to client.
Flow (client):
app init
set transferred state
[some other actions]
route activate action which lazy loads feature modules
What is the current behavior?
Any action (step 3) clears transferred state parts for not yet loaded modules. Transferred state is not available for lazy loaded modules (step 4).
Expected behavior:
Transferred state for lazy loaded modules is not cleared and is available upon loading.
Cause
Before lazy loaded module is loaded, its reducers are not yet registered. combineReducers runs for any action and clears any state parts that have no reducers registered, related code here
3. 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);
};
}
4. Use custom reducer factory
Custom combineReducers could be implemented preserving initial state
StoreModule.forRoot(APP_REDUCER_TOKEN, {
// same `combineReducers` with change from solution 1
reducerFactory: combineReducersCustom
}),
What would you suggest?
IMHO ideally this would be solved from ngrx side once, not requiring all consumers to implement one of these solutions (each having its own drawbacks).
The text was updated successfully, but these errors were encountered:
pawelgur
changed the title
Transfered (initial) state is cleared for lazy loaded modules
Transferred (initial) state is cleared for lazy loaded modules
May 9, 2019
I'm submitting a...
Prerequisites
Server side rendering set up with state transfer as per #101 - server state is set on client with custom action (triggered by effect) on app init by meta reducer:
App includes lazy loaded modules which are loaded on server side and their state is also transferred to client.
Flow (client):
What is the current behavior?
Any action (step 3) clears transferred state parts for not yet loaded modules. Transferred state is not available for lazy loaded modules (step 4).
Expected behavior:
Transferred state for lazy loaded modules is not cleared and is available upon loading.
Cause
Before lazy loaded module is loaded, its reducers are not yet registered.
combineReducers
runs for any action and clears any state parts that have no reducers registered, related code hereOther information:
Same issue mentioned in #324 (although refers to initial state, not transferred), similar in #906.
Possible solutions
1. Update
combineReducers
Update util to preserve state even for missing reducers, change this line to:
const nextState: any = {...state};
2. Provide default reducers for feature modules in root module
Details in this comment.
3. Manually set transferred state parts for lazy loaded modules
4. Use custom reducer factory
Custom
combineReducers
could be implemented preserving initial stateWhat would you suggest?
IMHO ideally this would be solved from ngrx side once, not requiring all consumers to implement one of these solutions (each having its own drawbacks).
The text was updated successfully, but these errors were encountered: