
React 18 Batching Patterns
OfficialFreeDiagnose and fix batching issues in React 18 class components.
Free · Opens the source repo
What React 18 Batching Patterns does
React 18 introduced automatic batching for state updates, which can lead to silent breaking changes in class components. This skill provides a comprehensive reference for diagnosing and fixing issues that arise from multiple setState calls in asynchronous methods, such as those found in setTimeout, Promises, or native event handlers. It is particularly useful for developers who are upgrading their React applications and need to ensure that their class components behave as expected under the new batching rules.
The core change in React 18 is that many asynchronous operations, which previously triggered immediate re-renders in React 17, are now batched. This means that all setState calls within a specific execution context are flushed together at the end of the execution, preventing intermediate renders. The skill outlines a decision tree to help developers quickly diagnose whether their code is affected by these changes and what steps to take to resolve any issues.
For developers facing test failures due to intermediate state assertions after upgrading to React 18, this skill serves as a guide to identify and correct the underlying problems. It emphasizes the importance of reading this.state after an await and provides clear categories for different scenarios, along with recommended solutions. Additionally, it advises on the judicious use of flushSync, which can bypass the benefits of React 18's concurrent rendering if overused.
By utilizing this skill, developers can refactor their class components effectively, ensuring that they adhere to the new batching behavior and maintain optimal performance in their applications.
When to use it
Use this skill when upgrading class components to React 18, especially when encountering issues with multiple `setState` calls in async methods.
When not to use it
This skill is not suitable for functional components or if you're not using class components in your React application.
What you can build with it
Upgrading a Legacy Codebase
When upgrading a legacy React application with class components to React 18, use this skill to identify and fix batching-related issues.
Debugging Test Failures
If you encounter test failures after upgrading to React 18, apply this skill to diagnose and correct the underlying state management problems.
Optimizing State Management
Use this skill to refine your class component's state management by understanding when to use `flushSync` and how to avoid unnecessary re-renders.
How to install React 18 Batching Patterns
View source1. Install with the skills CLI
npx skills add github/awesome-copilot/react18-batching-patterns --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by githubReact 18 Automatic Batching Patterns
Reference for diagnosing and fixing the most dangerous silent breaking change in React 18 for class-component codebases.
The Core Change
| Location of setState | React 17 | React 18 |
|---|---|---|
| React event handler | Batched | Batched (same) |
| setTimeout | Immediate re-render | Batched |
| Promise .then() / .catch() | Immediate re-render | Batched |
| async/await | Immediate re-render | Batched |
| Native addEventListener callback | Immediate re-render | Batched |
Batched means: all setState calls within that execution context flush together in a single re-render at the end. No intermediate renders occur.
Quick Diagnosis
Read every async class method. Ask: does any code after an await read this.state to make a decision?
Code reads this.state after await?
YES → Category A (silent state-read bug)
NO, but intermediate render must be visible to user?
YES → Category C (flushSync needed)
NO → Category B (refactor, no flushSync)
For the full pattern for each category, read:
references/batching-categories.md- Category A, B, C with full before/after codereferences/flushSync-guide.md- when to use flushSync, when NOT to, import syntax
The flushSync Rule
Use flushSync sparingly. It forces a synchronous re-render, bypassing React 18's concurrent scheduler. Overusing it negates the performance benefits of React 18.
Only use flushSync when:
- The user must see an intermediate UI state before an async operation begins
- A spinner/loading state must render before a fetch starts
- Sequential UI steps have distinct visible states (progress wizard, multi-step flow)
In most cases, the fix is a refactor - restructuring the code to not read this.state after await. Read references/batching-categories.md for the correct approach per category.
Frequently asked questions about React 18 Batching Patterns
Similar skills
React Composition Patterns
Streamline your React component architecture with proven patterns.
Pester Should Migration
Easily convert Pester v5 assertions to v6 syntax.
Radix to Base UI Migration
Seamlessly migrate React components from Radix UI to Base UI.
Migrate Next.js to Vinext
Seamlessly transition your Next.js projects to Vinext.
WinUI 3 Migration Guide
Streamline your UWP to WinUI 3 migration process.
Refactor
Enhance code maintainability without altering behavior.
