Understanding Redux Thunk
Redux-Thunk is the most popular middleware that manages asynchronous actions in Redux.
Redux Thunk middleware allows you to write action creators that return a function instead of an action.
Don’t fall into the trap of thinking a library should prescribe how to do everything. If you want to do something with a timeout in JavaScript, you need to use setTimeout
. There is no reason why Redux actions should be any different.
Redux does offer some alternative ways of dealing with asynchronous stuff, but you should only use those when you realize you are repeating too much code. Unless you have this problem, use what the language offers and go for the simplest solution.
So, without any middleware, your action creator might look like
// action creator
function loadData(dispatch, userId) {
// needs to dispatch, so it is first argument
return fetch(`http://api.com/${userId}`)
.then(res => res.json())
.then(
data => dispatch({ type: 'LOAD_SUCCESS_DATA', data }),
err => dispatch({ type: 'LOAD_FAILURE_DATA', err })
);
}// component
componentWillMount() {
loadData(this.props.dispatch, this.props.userId);
// don't forget to pass dispatch
}
But with Thunk Middleware you can write it like this:
// action creator
function loadData(userId) {
// Redux Thunk handles these
return dispatch => fetch(`http://api.com/${userId}`)
.then(res => res.json())
.then(
data => dispatch({ type: 'LOAD_SUCCESS_DATA', data }),
err => dispatch({ type: 'LOAD_FAILURE_DATA', err })
);
}// component
componentWillMount() {
this.props.dispatch(loadData(this.props.userId));
// dispatch like you usually do
}
So there is no huge difference. One thing I like about the latter approach is that the component doesn’t care that the action creator is async. It just calls dispatch normally, it can also use mapDispatchToProps
to bind such action creator with a short syntax, etc. The components don’t know how action creators are implemented, and you can switch between different async approaches (Redux Thunk, Redux Promise, Redux Saga) without changing the components. On the other hand, with the former, explicit approach, your components know exactly that a specific call is async, and needs dispatch to be passed by some convention (for example, as a sync parameter).
For simple apps, the approach should suffice. Don’t worry about middleware if you’re happy with it.
In larger apps, however, you might find certain inconveniences around it.