21

Both Redux Thunk and Redux Saga are middleware of Redux. What is the difference between two and how to determine when to use Redux Thunk or Redux Saga?

MERLIN THOMAS
  • 475
  • 1
  • 5
  • 13
  • 1
    Possible duplicate of [Pros/cons of using redux-saga with ES6 generators vs redux-thunk with ES2017 async/await](https://stackoverflow.com/questions/34930735/pros-cons-of-using-redux-saga-with-es6-generators-vs-redux-thunk-with-es2017-asy) – Roy Wang May 11 '18 at 06:07

2 Answers2

42

Both Redux Thunk and Redux Saga take care of dealing with side effects. In very simple terms, applied to the most common scenario (async functions, specifically AJAX calls) Thunk allows Promises" to deal with them, Saga uses Generators. Thunk is simple to use and Promises are familiar to many developers, Saga/Generators are more powerful but you will need to learn them. When Promises are just good enough, so is Thunk, when you deal with more complex cases on a regular basis, Saga gives you better tools.

As an example, What happens when you start an AJAX call in a route/view and then the user moves to a different one? Can you safely let the reducer change the state anyway? Saga makes it trivial to cancel the effect, Thunk requires you to take care of it, with solutions that don't scale as nicely.

In practical terms choosing one or the other one really depends (tautologically) on the project.

One thing to keep in mind is that the two middleware can coexists, so you can start with Thunks and introduce Sagas when/if you need them (and then choose how/what to refactor with hands on experience... A solution that especially fits "learning projects", MVPs, et similia) In general terms, Sagas are more powerful and easier to test, but they introduce many new concepts, that can be a bit overwhelming if you're also learning other technologies (Redux especially).

Specifically, while dealing with the simple and effective Redux philosophy (actions (literal objects) fed into reducers (pure functions)), you can deal with side effects with Thunk that is more limited but easy to grasp (Promise.then().error()), or with Saga that requires you to face the (powerful) notion that you can do more complex things with those actions.

It's also worth mentioning (redux-)observable as an even more complex (and even more pawerful) paradigm to deal with side effects, just in case you are familiar with it (if you already are, it might be easier to use than learning Saga).

user4634576
  • 521
  • 3
  • 3
8

Actually, Both of them are middleware for Redux to deal with asynchronous actions. For knowing the difference between then please pay attention to the following picture:

Architect of Redux

The middleware box generally refers to software services that glue together separate features in existing software. For Redux, middleware provides a third-party extension point between dispatching an action and handing the action off to the reducer. then reducer makes the new state.

Redux Thunk is a middleware that lets you call action creators that return a function instead of an action object. That function receives the store’s dispatch method, which is then used to dispatch regular synchronous actions inside the body of the function once the asynchronous operations have completed. simple, easy to learn and use with 352B volume

Redux Saga leverages an ES6 feature called Generators, allowing us to write asynchronous code that looks synchronous, and is very easy to test. In the saga, we can test our asynchronous flows easily and our actions stay pure. complicated, hard to learn and understand, 14kB volume but organized complicated asynchronous actions easily and make then very readable and the saga has many useful tools to deal with asynchronous actions

HINT: If you cannot understand the difference between them or understand the redux-saga flow but still you wanna have readable code and avoid callback hell, go after redux-thunk by using async/await, I leave an example for offer:

// simple usage of redux-thunk:
export const asyncApiCall = values => {
  return dispatch => {
    return axios.get(url)
      .then(response =>{
        dispatch(successHandle(response));
      })
      .catch(error => {
        dispatch(errorHandle(error));
      });
    };
  };



// async/await usage of redux-thunk:
export const asyncApiCall = values => {
  return async dispatch => {
    try {
      const response = await axios.get(url);
      dispatch(successHandle(response));
    }
    catch(error) {
      dispatch(errorHandle(error));
    }
  };
};
AmerllicA
  • 15,720
  • 11
  • 72
  • 103