Redux and within a reducer accessing a different r

2019-03-25 18:52发布

问题:

So, I have an app that has multiple reducers, and thus multiple action creators associated.

There is a time in which one of my reducers updates the state (because of an edit), and as such, I have to then make sure the other reducers see this update and adjust their state accordingly.

think of it as if a user selects "sneakers", and this state management is in a reducer called productsReducer. As such, as a user moves thru the app process, they get couponsReducer associated with it... but the user can "edit" at any time, so if they then edit "sneakers" and say, choose another producer, I have to be able to alter the couponsReducer in real time, because a progress modal needs to reflect this. I can do this via going thru the flow to the coupon page, because on that page I just reconcile the data on componentWillMount... but the rub is I have a progress modal, and prior to getting to the coupons page, a user can open the progress modal... and there will be a missmatch here...

long winded I know, I just wanted to explain my situation.

so, I want to be able to call "other reducers" or their action creators from within the productsReducer.

Would a middleware be appropriate here, in which I sniff for a certain "action.type" and if I see it, I can dispatch other action.type's or is there a way to call action creators from within the productsReducer?

importing: import * as coupons from './couponsActions' and any other actions I need seem inappropriate.

回答1:

Updating state based on the state of application is an anti-pattern. The solution is even simpler:

If an action affects multiple reducers, subscribe to that action in the reducers that care.

So when a user selects sneakers, fire these actions

{ type: 'item_select', payload: 'sneakers' }

and then in couponsReducer, have something like this:

function (state = initialState, action) {
  if (action.type == 'item_select') {
    return { ...state, activeProduct: action.payload);}
  }
  return state;
}

You do not want cascading updates, where states depend on other states changing. You want a simple dispatch architecture where one action affects everything all at once.



回答2:

In many cases it is enough to handle the same action in multiple reducers (which is an officially recommended way of doing things in redux). So always try that solution first.

In more complex cases there are some libraries you can use. For example using redux-saga you could handle it like this:

function* watchItemSelect() {
    while(true) {
        // Wait for the action you are interested in
        const action = yield take('ITEM_SELECT');
        // Send another action
        yield put({type: 'OTHER_ACTION'}) 
        // The loop will now continue and wait until the next ITEM_SELECT action comes
    }
}

There are also other libraries that does the same thing but a little different. Most of them inspired by the elm language:

  • redux-loop
  • redux-side-effect
  • redux-side-effects
  • redux-effects

Also this repo has some info about the thinking in the above libraries:

redux-architecture