Divs
Divs

Reputation: 1618

Angular2 - Is sharing action between reducers a Bad idea?

We are using ngrx / store in our Angular 2 app. Our store is combined of Reducers "cameraReducer", "subjectReducer" ... and we want to maintain a few global and also common (across diff functionalities) items like "Loading Data" properties in "appReducer".

In a scenario like this, does it make sense to share an action like {type:LOADING_*, payload} between individualReducers and appReducer? This should be turned on while a functionality (which can be thought of like one singular piece of data operation [using a single Reducer and a single action] or multiple related data operations [using multiple reducers and multiple actions]) is started and turned off once completed. The appReducer can look like this:

case LOADING_CAMERA:
     LOADING_SUBJECT:
            return state.setIn('loading') = true;

Adv - No Boilerplate. Cons - Ordering of reducers will play a role as to when the indicator pops on/off.

Or

case LOADING:
        return state.setIn('loading') = true;

we can have code like at the beginning / end of the invoking each functionality

 this.store.dispatch({action:'LOADING', payload: true}); 
 //functionality
 this.store.dispatch({action:'LOADING', payload: false}); 

Adv - Controlled Ordering of Indicator pop on/off. Cons - Boilerplate code to turn on/off loading.

Or

We can try to compute the "loading" as a combined observables (with each reducer having their own local "loading" property and an Observable of that property).

Adv - No Boilerplate and Controlled Ordering on indicator on/off. Cons - Increased complexity and more code may be.

Upvotes: 1

Views: 1236

Answers (2)

Derek Kite
Derek Kite

Reputation: 1825

There is also the option of using Effects. You can subscribe to changes in StateUpdates which triggers whenever there is a state change. I find the example app at https://github.com/ngrx/example-app to be a great source of information on how to structure the app and ngrx.

For example,

@Effect() loadCollection$ = this.updates$
    .whenAction(BookActions.LOAD_COLLECTION)
    .switchMapTo(this.db.query('books').toArray())
    .map((books: Book[]) => this.bookActions.loadCollectionSuccess(books));

When the LOAD_COLLECTION is dispatched, this is called which does the background work and dispatches the LOAD_COLLECTION_SUCCESS which updates the component. It seems that any impure function that has side effects work best this way, leaving only pure functions in the reducers.

Upvotes: 0

markerikson
markerikson

Reputation: 67449

The typical approach to organizing a Redux store is to structure your data by some kind of domain per key, and to define a reducer function that is given delegated responsibility for maintaining updates to that slice of state, usually composed with the combineReducers utility. Redux absolutely encourages you to have multiple sub-reducer functions responding to the same incoming actions, so that sliceA and sliceB are independently updated as appropriate. Ordering should not be a concern, as each sub-reducer is generally unaware of any other parts of the state, and only concerned with updating its own slice. See this answer in the Redux FAQ for some related info: http://redux.js.org/docs/FAQ.html#reducers-share-state .

Upvotes: 2

Related Questions