Blogged Answers: Reasons to Use Thunks
This is a post in the Blogged Answers series.
Two years ago, I addressed a number of concerns about using both thunks and sagas for async logic in my post Thoughts on Thunks, Sagas, Abstraction, and Reusability.
I continue to see a number of folks argue that thunks lead to code that is "unmaintainable and untestable", and I want to lay out some reasons why I don't think that is the case.
I'd agree that thunks are somewhat less testable, but it also depends on what you want to try to test and how you want to test it. For example, thunks that make AJAX calls can be tested by mocking out whatever your AJAX lib is, whether it be via something like jest.mock()
, or writing your thunks to use the extraArgument
setup option and injecting a service object for it to use for the API calls, and that can be replaced with a mock version in a test.
It's certainly a different approach to testing logic than running a generator function and asserting that each yielded effect is as expected, but it's still a valid way to test the logic.
On the other hand, I've seen a number of folks complain that testing sagas often degenerates to effectively testing implementation details of the saga, vs the final result.
So, I really don't think the "testability" concern is as clear-cut as some people argue.
On the flip side, thunks can do some things that sagas cannot:
- Thunks can synchronously execute logic, including
dispatch()
andgetState()
, and continue to do more work immediately - Thunks can return a value such as a promise to the site that dispatched them, allowing you to do things like executing component logic after a fetch has completed
- Thunks do not require creating extra actions to act as "signals" just to kick off a saga in the background, so they're simpler that way
- The thunk middleware is only 15-ish lines long, while the saga middleware is 5.3K min+gz.
redux-cofx
appears to be less hefty, at 2.8K min+gz, but both of those do add additional size.redux-observable
is only 1.5K, but also requires whatever portions of RxJS you're using.
In addition, redux-saga
and redux-cofx
require understanding of both generator syntax and the specific library APIs, while redux-observables
requires understanding observables and the RxJS API. Those add considerable mental overhead.
I think a lot of the complaints about thunks are due to concerns about nested promise chains, and I'll fully agree that those are not particularly easy to read or maintainable. However, async/await
syntax makes that a lot cleaner to work with.
Again, I'm not saying thunks are the only solution you should use, or that sagas/observables/generators are bad and you should never use. All I'm saying is that thunks are a perfectly acceptable tool for a variety of use cases, and that they make a suitable default approach for folks to use for async logic with Redux.
This is a post in the Blogged Answers series. Other posts in this series:
- Aug 08, 2023 - Blogged Answers: My Experience Modernizing Packages to ESM
- Jul 06, 2022 - Blogged Answers: How I Estimate NPM Package Market Share (and how Redux usage compares to other libraries)
- Jun 22, 2021 - Blogged Answers: The Evolution of Redux Testing Approaches
- Jan 18, 2021 - Blogged Answers: Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)
- Jun 21, 2020 - Blogged Answers: React Components, Reusability, and Abstraction
- May 17, 2020 - Blogged Answers: A (Mostly) Complete Guide to React Rendering Behavior
- May 12, 2020 - Blogged Answers: Why I Write
- Feb 22, 2020 - Blogged Answers: Why Redux Toolkit Uses Thunks for Async Logic
- Feb 22, 2020 - Blogged Answers: Coder vs Tech Lead - Balancing Roles
- Jan 19, 2020 - Blogged Answers: React, Redux, and Context Behavior
- Jan 01, 2020 - Blogged Answers: Years in Review, 2018-2019
- Jan 01, 2020 - Blogged Answers: Reasons to Use Thunks
- Jan 01, 2020 - Blogged Answers: A Comparison of Redux Batching Techniques
- Nov 26, 2019 - Blogged Answers: Learning and Using TypeScript as an App Dev and a Library Maintainer
- Jul 10, 2019 - Blogged Answers: Thoughts on React Hooks, Redux, and Separation of Concerns
- Jan 19, 2019 - Blogged Answers: Debugging Tips
- Mar 29, 2018 - Blogged Answers: Redux - Not Dead Yet!
- Dec 18, 2017 - Blogged Answers: Resources for Learning Redux
- Dec 18, 2017 - Blogged Answers: Resources for Learning React
- Aug 02, 2017 - Blogged Answers: Webpack HMR vs React-Hot-Loader
- Sep 14, 2016 - How I Got Here: My Journey Into the World of Redux and Open Source