store
store copied to clipboard
Fractal store configuration questions
This is a...
- [x] usage question
What toolchain are you using for transpilation/bundling?
- [x] angular/cli
I've got 2 questions regarding fractal store setup:
1. Fractal store article implies that it has to be defined on component level (https://github.com/angular-redux/store/blob/master/articles/fractal-store.md). Can it be configured on module level so no additional code in each component is required or does it have to be configured for each component? 2. How can I supply initial state for fractal store? I need this specifically for lazy loaded modules that come from separate npm packages. Scenario is:
- main redux store is configured on host application level
- user navigates to specific route, feature that will have it's own fractal store is lazily loaded
- I would like to supply initial state for this fractal store from lazily loaded module
This way host application doesn't need to know about state of this lazily loaded feature upfront which is important to keep separation of concerns between host/feature package and avoids adding initial state for something that potentially won't be used.
Currently it would still need to be configured at the root component of that module.
The configureSubStore currently does not accept a parameter for an initial state, although I don't think that would be too hard of a fix to add.
In the meantime though, would something like:
export const lazyReducer = (initialState) => (state, action) =>
action.type === 'ADD_LOC' ?
{ ...state, loc: state.loc + action.payload } :
state;
// in the component
ngOnInit() {
this.subStore = this.ngRedux.configureSubStore(
['users', userId], lazyReducer(initialState));
}
work to solve your use-case?
thanks for reply but unfortunately your suggestion doesn't solve my use case. I'm using @WithSubStore decorator, here's my setup:
I've got base class from which angular components inherit (this way I don't need to setup substore in each component)
@WithSubStore({
basePathMethodName: 'getBasePath',
localReducer: rootReducer
})
export class AppSubStore {
getBasePath(): PathSelector {
return ['mySubstore']
}
}
then, rootReducer:
export const rootReducer: Reducer<IAppState> = combineReducers({
something: somethingReducer,
somethingElse: somethingElseReducer
}) as Reducer<IAppState>;
and example reducer:
export interface ISomething {
value: number;
}
export const INITIAL_SOMETHING_STATE: ISomething = {
value: 123
}
export function somethingReducer(state: ISomething = INITIAL_SOMETHING_STATE, action: Action): ISomething {
switch (action.type) {
case 'CHANGE_VALUE': return { ...state, value: Math.random() };
}
return state;
}
how can I initialize default state in such setup?
Why do you use the rootReducer for the substore? I use an additional reducer-function as the localReducer of the substore. If I would add that with combineReducers to the root-store, it will be called twice.
So I have the inital state of the substore at the localReducer like in your example of somethingReducer. And my app-module doesn't have to know anything about the substate and reducers of the sub-module.
rootReducer is in fact a local reducer defined for lazy loaded code with it's own substore. I see why variable name caused you confusion though, sorry about that. to clarify - all of the code snippets I provided live in separate package which is lazy loaded.
problem with setup I outlined is that when code containing this implementation is lazy loaded, initial state for substore is initialized only after some action is dispatched. I'd like to initial state to be initialized when code is lazy loaded.
Ah, I see.
You can use the constructor of the lazy loaded module to dispatch a special init-action. It's a bit ugly but not the worst thing, I guess.
yeah, that works but I'd prefer to have built in mechanism rather than resorting to work arounds