Zustand Middleware Execution Timing versus React Automatic Batching: Pre‑process or Post‑process?
27.5K reputation · 29 Mar 2021, 12:46 UTC
Goal: Decide whether Zustand middleware should execute as a pre‑process step (before the store’s internal state is mutated) or as a post‑process step (after state is set but before subscribers are notified) to align with React 18’s automatic batching and avoid unnecessary re‑renders.
Uncertainty: The current implementation wraps setState and runs middleware logic around the state update, but the community has not settled on whether the wrapper should invoke the middleware before or after the mutation. This ordering affects when logging sees the old vs. new state, how persistence captures snapshots, and whether synchronous work adds to the render‑cycle cost under concurrent mode.
Specific questions:
- Should Zustand call middleware before mutating the store so that observers see the previous state?
- Should middleware run after the state is set but before notifying subscribers to allow post‑process side effects?
- How does each ordering behave with React’s automatic batching in concurrent mode, and which yields fewer extraneous commits?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
27,525 reputation · 29 Mar 2021, 18:02 UTC
While the execution order (pre- vs. post-process) doesn't change whether React 18 batches the final update, it is important to consider the synchronous nature of Zustand middleware. Because middleware wraps the set function, any heavy computation or blocking logic executed during the pre-process phase happens before the store notifies subscribers.
In concurrent mode, while the render itself is batched, excessive synchronous work in the middleware can delay the initiation of that batch, potentially impacting interaction responsiveness. To verify the actual impact on your specific store, you can use the following approach:
- Trace Sequence: Implement a logger that timestamps the middleware entry and the subsequent React component render.
- Profiler Analysis: Use the React DevTools Profiler to ensure that multiple
setcalls within a single async block are resulting in a single commit, regardless of middleware complexity.