rxjs - Angular 2 update global state as a side effect of updating a certain state -
i want achieve setting global state while requesting data api , storing in state well, in location global state.
i'm calling effect (models.effects.ts
):
@effect() models$: observable<action> = this.actions$ .oftype(get_models) .switchmap(() => this.modelsapi.getmodels()) .map(models => ({type: set_models, payload: models})) .catch((err: any) => observable.of({type: get_failure, payload: {error: err}}))
now want this:
@effect() models$: observable<action> = this.actions$ .oftype(get_models) .do(() => this.store.dispatch({type: 'set_loading_state', payload: true})) .switchmap(() => this.modelsapi.getmodels()) .map(models => ({type: set_models, payload: models})) .do(() => this.store.dispatch({type: 'set_loading_state', payload: false})) .catch((err: any) => observable.of({type: get_failure, payload: {error: err}}))
as can see we're dispatching call globalreducer
(global.reducer.ts
):
export const globalreducer: actionreducer<any> = (state: iglobalstorage = {isloading: false}, action: action) => { switch(action.type) { case set_loading_state: return object.assign({}, state, { isloading: action.payload }); default: return state; } }
which mean update global state isloading
before , after make http request. however, solution both messy , not work because of simple fact breaks effect (for whatever reason, think it's because call dispatch within effect).
preferably create effect listens set_loading_state
calls globalreducer
itself, rather letting models$
effect directly.
something (from within global.effects.ts
):
@effect() loadingstate$: observable<action> = this.actions$ .oftype(set_loading_state) .do(() => ({type: set_loading_state, payload: thepayloadthatwassent}))
but there 2 problems that:
- i don't know how access sent payload in effect.
- i don't know how call effect within
models$
effect.
overall i'm confused on how achieve want , there aren't examples of far i've been able find.
if @ image, want update global.isloading
when update models
:
what best way achieve want?
storing isloading
indicator in central place similar done error information. 1 solution storing central error involves using reducer ignores actions' types , looks see if contain error
property.
if adopt suitable naming scheme effects' action types, same thing isloading
.
one possible naming scheme be:
some_action_request some_action_response some_action_error
with such scheme, following reducer examine action types , set isloading
state accordingly:
export function isloadingreducer(state: boolean = false, action: action): boolean { if (/_request$/.test(action.type)) { return true; } else if (/(_response|_error)$/.test(action.type)) { return false; } else { return state; } }
using boolean
value isloading
assumes not have concurrent asynchronous effects, if that's issue, extend reducer use counter instead.
if wire things way, isloading
indicator doesn't need know individual effects , vice versa.
Comments
Post a Comment