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 middlewares can coexist, 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 has an even more complex (and even more powerful) paradigm to deal with side effects, just in case you are unfamiliar with it (if you already are, it might be easier to use than learning Saga).