98
votes

As far as I know and correct me if I am wrong, redux-thunk is a middleware which helps us dispatch async function and debug values in the action itself while when I used redux-promise I couldn't create async functions without implementing my own mechanism as Action throws an exception of dispatching only plain objects.

What is the major differences between these two packages? Are there any benefits of using both the packages in a single page react app or sticking to redux-thunk would be enough?

3

3 Answers

127
votes

redux-thunk allows your action creators to return a function :

function myAction(payload){
    return function(dispatch){
        // use dispatch as you please
    }
}

redux-promise allows them to return a promise :

function myAction(payload){
    return new Promise(function(resolve, reject){
        resolve(someData); // redux-promise will dispatch someData
    });
}

Both libraries are useful if you need to dispatch action async or conditionally. redux-thunk also allows you to dispatch several times within one action creator. Whether you choose one, the other or both entirely depends on your needs/style.

84
votes

You'll likely want/need both together in your app. Start with redux-promise for routine promise-producing async tasks and then scale up to add Thunks (or Sagas, etc.) as complexity increases:

  • When life is simple, and you're just doing basic async work with creators that return a single promise, then redux-promise will improve your life and simplify that, quick and easy. (In a nutshell, instead of you needing to think about 'unwrapping' your promises when they resolve, then writing/dispatching the results, redux-promise(-middleware) takes care of all that boring stuff for you.)
  • But, life gets more complex when:
    • Maybe your action creator wants to produce several promises, which you want to dispatch as separate actions to separate reducers?
    • Or, you have some complex pre-processing and conditional logic to manage, before deciding how and where to dispatch the results?

In those cases, the benefit of redux-thunk is that it allows you to encapsulate complexity inside your action-creator.

But note that if your Thunk produces and dispatches promises, then you'll want to use both libraries together:

  • the Thunk would compose the original action(s) and dispatch them
  • redux-promise would then handle unwrapping at the reducer(s) the individual promise(s) generated by your Thunk, to avoid the boilerplate that entails. (You could instead do everything in Thunks, with promise.then(unwrapAndDispatchResult).catch(unwrapAndDispatchError)... but why would you?)

Another simple way to sum up the difference in use-cases: the beginning vs. the end of the Redux action cycle:

  • Thunks are for the beginning of your Redux flow: if you need to create a complex action, or encapsulate some gnarly action-creation logic, keeping it out of your components, and definitely out of reducers.
  • redux-promise is for the end of your flow, once everything has been boiled down to simple promises, and you just want to unwrap them and store their resolved/rejected value in the store

NOTES/REFS:

  • I find redux-promise-middleware to be a more complete and understandable implementation of the idea behind the original redux-promise. It's under active development, and is also nicely complemented by redux-promise-reducer.
  • there are additional similar middlewares available for composing/sequencing your complex actions: one very popular one is redux-saga, which is very similar to redux-thunk, but is based on the syntax of generator functions. Again, you'd likely use it in conjunction with redux-promise.
  • Here's a great article directly comparing various async composition options, including thunk and redux-promise-middleware. (TL;DR: "Redux Promise Middleware reduces boilerplate pretty dramatically vs some of the other options" ... "I think I like Saga for more complex applications (read: "uses"), and Redux Promise Middleware for everything else.")
  • Note that there's an important case where you may think you need to dispatch multiple actions, but you really don't, and you can keep simple things simple. That's where you just want multiple reducers to react to your async call. But, there's no reason at all why multiple reducers can't monitor a single action type. You'd simply want to make sure that your team knows you're using that convention, so they don't assume only a single reducer (with a related name) can handle a given action.
22
votes

Full disclosure: I'm relatively new to Redux development and struggled with this question myself. I'll paraphrase the most succinct answer I found:

ReduxPromise returns a promise as the payload when an action is dispatched, and then the ReduxPromise middleware works to resolve that promise and pass the result to the reducer.

ReduxThunk, on the other hand, forces the action creator to hold off on actually dispatching the action object to the reducers until dispatch is called.

Here's a link to the tutorial where I found this info: https://blog.tighten.co/react-101-part-4-firebase.