What is the difference between redux-thunk and redux-promise?
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.
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, withpromise.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 originalredux-promise
. It's under active development, and is also nicely complemented byredux-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 toredux-thunk
, but is based on the syntax of generator functions. Again, you'd likely use it in conjunction withredux-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.
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.