Search code examples
javascriptasynchronousreactjsreduxredux-thunk

What are the benefits of using thunk middleware in redux over using regular functions as async action creators?


I've been using redux for about two months now and have just recently started getting into exploring different ways of dealing with asynchronous behavior such as fetching data. It appears from the documentation and from discussions on GitHub that the standard way of doing this by using the thunk middleware which is a pretty simple concept however I'm not sure if I understand the benefit in handing the responsibility of executing async state machines to redux middleware when a simple independent function could have been used.

Traditional Redux approach using thunk middleware

Async Action Creator fetchPosts

function fetchPosts(reddit) {
  return dispatch => {
    dispatch(requestPosts(reddit))
    return fetch(`http://www.reddit.com/r/${reddit}.json`)
      .then(response => response.json())
      .then(json => dispatch(receivePosts(reddit, json)))
  }
}

Then perhaps in a ReactJS component one may have a button such as the one below.

Dispatching fetchPosts

<button onClick={() => this.props.dispatch(fetchPosts(this.props.reddit))} />

This button when clicked calls the async action creator requestPosts which returns a function that accepts the dispatch and is responsible for carrying out any async code which may have side effects and also dispatching the true actions that may result.

Slightly simpler example without thunk middleware

While the above is completely understandable it's unclear why one would not prefer just to do something slightly more simplistic like in the example below.

Delegated async dispatching without an action creator

function fetchPosts(dispatch, reddit) {
  dispatch(requestPosts(reddit))
  return fetch(`http://www.reddit.com/r/${reddit}.json`)
    .then(response => response.json())
    .then(json => dispatch(receivePosts(reddit, json)))
}

Calling the fetchPosts function and passing the dispatch as an argument.

<button onClick={() => fetchPosts(this.props.dispatch, this.props.reddit)} />

Conclusion

Based on the two examples side by side I don't see how the async action creator using thunk middleware buys me anything and it requires added complexity in setting up the middlware and introduces two varieties of action creators (1) pure functions which return a single action to be dispatched (2) impure functions that will feedback actions and perhaps other thunks into the dispatcher. I feel like I'm missing something here which would explain the benefits of dispatching something other than an immutable action in redux.


Solution

  • This is very well tread territory. I'd say that it's a common sentiment that async action creators aren't particularly satisfying, but there are good reasons to prefer Redux Thunk to the completely manual approach. But it is just one of a number of possible approaches. See Why do we need middleware for async flow in Redux?.

    I think the community will probably settle on something other than Redux Thunk in the long run, but its simplicity makes it a good starting point.