27

I read that Redux Thunk is the reliable way to manage asynchronous actions/request. There's nothing much about dispatching actions by other actions.

How about dispatching synchronous actions? I am not sure of thunk approach's performance issues, but can I just dispatch action inside other action creator without defining function inside?

It seems to me that using redux thunk is unnecessary for this need.

Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
Rafał Łyczkowski
  • 995
  • 2
  • 11
  • 27
  • Why do you want your action creators to dispatch multiple synchronous actions? This seems like unnecessary indirection and complexity. There's probably a better way. – David L. Walsh Feb 18 '16 at 22:41
  • 1
    This usage has been described here: http://stackoverflow.com/questions/34570758/why-do-we-need-middleware-for-async-flow-in-redux Instead of multiuple reducers consuming same action I would like to trigger particulary action with other action (for example, to notify { type: 'DISPLAY_NOTIFICATION', text: '' } – Rafał Łyczkowski Feb 18 '16 at 22:52

3 Answers3

38

Showing and hiding notification does indeed appear to be a good use case for thunks.

David’s answer describes the “default” way of doing several updates in response to something: handle it from different reducers. Most often this is what you want to do.

Sometimes (as with notifications) it can be inconvenient. I describe how you can choose between dispatching one or several actions in my answer to this question.

In case when you do decide to dispatch multiple actions, either just do it sequentially from your components, or use Redux Thunk. Note that if Redux Thunk seems mysterious to you, you should understand what it really is before using it. It only provides benefits in terms of code organization; in reality it’s not any different from running dispatch() two times in a row yourself.

That said, with Redux Thunk dispatching multiple actions looks like this:

function increment() {
  return { type: 'INCREMENT' }
}

function incrementTwice() {
  return dispatch => {
    dispatch(increment())
    dispatch(increment())
  }
}

store.dispatch(increment())
incrementTwice()(store.dispatch) // doesn’t require redux-thunk but looks ugly
store.dispatch(incrementTwice()) // requires redux-thunk but looks nice

Using Redux Thunk will not have any performance issues. It’s just a nice way of calling functions to which you can hand over your dispatch so they can do it as many times as they want.

Community
  • 1
  • 1
Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
  • 5
    How should I implement the requirement that second dispatch only starts when first dispatch finished transforming the state?. – Anand Aug 12 '16 at 06:40
  • @SutikshanDubey Did you find answer to your question? I also need kind of thing you asking - to make several dispatches() but snyc. – Ali Zeynalov Jun 29 '18 at 17:25
  • 1
    dispatches which contain synchronous method calls, when run from thunk based middleware run synchronously. as Dan suggested above, I put my dispatches in thunk based middleware. When put inside component, yes, you may not be sure as React optimizes state update by batching it. – Anand Jun 30 '18 at 22:24
18

It's a mistake to think of actions to state changes as one-to-one. They are in fact many-to-many. Remember that all actions are called on all reducers.

For instance, a single action might trigger several state changes:

function firstReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // handle action x
    }
}

function secondReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // handle action x
    }
}

function thirdReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // handle action x
    }
}

Conversely, the same state change might result from two different actions.

function firstReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
        case ACTION_Y:
            // handle action x and y in the same manner
    }
}

It might seem odd to handle two actions in the same manner, but this is only in the context of a single reducer. Other reducers are free to handle them differently.

function secondReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // handle action x
        case ACTION_Y:
            // handle action y
    }
}

function thirdReducer(state, action) {
    switch (action.type) {
        case ACTION_X:
            // handle action x
        default:
            // ignore action y
    }
}

With this many-to-many relationship, it's simply unnecessary to have an action hierarchy. If you have action creators firing multiple synchronous actions, your code becomes more complex and harder to reason about.

David L. Walsh
  • 24,097
  • 10
  • 61
  • 46
  • http://redux.js.org/docs/recipes/ReducingBoilerplate.html here in actionCreators.js using middleware there are multiple actions dispatched by single action Creator. Instead of complexity if we could dispatch other action this will prevent redefining particulary reducers with new action types. I just can imagine that Notificationreducer should be alterated with a new action type just because I want to fullfill its state by any other action. – Rafał Łyczkowski Feb 18 '16 at 23:35
  • As far as I can tell, none of the examples on that page fire multiple synchronous actions. There's a synchronous LOAD_POSTS_REQUEST action dispatched, followed by the asynchronous LOAD_POSTS_REQUEST/LOAD_POSTS_FAILURE. – David L. Walsh Feb 18 '16 at 23:52
2

If this makes it through, then yes, using:

store.dispatch(action1, action2)

Maybe +1 at github?

Robert Plummer
  • 634
  • 1
  • 5
  • 13