Blogged Answers: A Comparison of Redux Batching Techniques
This is a post in the Blogged Answers series.
The Redux FAQ has an entry on "how to reduce the number of store update events". This ties into the somewhat common question of "how do I batch actions with Redux?".
There's a Redux issue from 2016 where a user tried to suggest changing dispatch
to accept multiple action arguments at once. That PR was rejected because the attempted implementation failed to consider how the changes would interact with the rest of the ecosystem, and because solutions could be implemented in userland.
There's multiple tools and approaches available for "batching" with Redux, and they all work at different levels and in different ways. During that discussion, I did a bunch of research on how Redux actually behaves and how these libraries implement forms of batching.
I'll summarize the major options:
redux-batched-actions
: a higher-order reducer that wraps multiple sub-actions in a larger"BATCH"
action. If you pass multiple actions to the batchActions action creator, it creates a new action that puts the array of actions as the payload. The higher-order reducer wraps around your "real" reducer, looks for thattype : "BATCH"
action, and calls your "real" reducer repeatedly with each action in the array. Since the higher-order reducer is only being executed once, from the store's perspective it's all one action being handled by one call to the reducer, so there's only one notification. However, this limits how things like middleware might interact with the dispatched actions, and also makes it harder to read them in the DevTools.redux-batched-subscribe
: A store enhancer that wraps the real store'sdispatch
method. It allows you to provide your own subscriber notification callback, which might use something like_.debounce()
or React'sunstable_batchedUpdates()
API to limit how many times the UI actually attempts to re-render when multiple actions are dispatched in close sequence.redux-batch
: a store enhancer that wraps the store'sdispatch
andsubscribe
methods. It allows you to pass an array of actions todispatch
, passes them to the real store'sdispatch
one at a time, but then only notifies subscribers once the entire array has been processed. This allows the individual actions to still show up in the DevTools separately, but only results in a single notification event.- React-Redux's
batch
API: this is just React'sunstable_batchedUpdates()
API, re-exported and renamed. It allows you to provide a callback where multiple React state updates are queued, but only have a single render pass as a result. If you're dispatching Redux actions inside, each dispatched action would still result in a separate notification of subscribers (and running ofmapState
functions), but the rendering would get combined.
So, it's really a question of what your goal is for "batching actions", and where you want the modification of the process to occur. Given the variety of use cases, you can see why we chose not to implement anything like this directly in the Redux core - there's just too many different use cases, and they can be handled in userland.
That means that if you're using redux-batched-actions
and redux-saga
together, you'd have to specifically be watching for the "BATCH"
action type in your sagas, rather than looking for the specific individual action types, and you'd have to unpack those actions yourself. If you're using redux-batch
, on the other hand, I think you should be able to listen for the individual actions as normal.
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