mirror of
https://github.com/github/awesome-copilot.git
synced 2026-04-11 10:45:56 +00:00
- Adds React 18 and 19 migration orchestration plugins - Introduces comprehensive upgrade toolkits for migrating legacy React 16/17 and 18 codebases to React 18.3.1 and 19, respectively. Each plugin bundles specialized agents and skills for exhaustive audit, dependency management, class/component API migration, test suite transformation, and batching regression fixes. - The React 18 toolkit targets class-component-heavy apps, ensures safe lifecycle and context transitions, resolves dependency blockers, and fully automates test migrations including Enzyme removal. The React 19 toolkit addresses breaking changes such as removal of legacy APIs, defaultProps on function components, and forwardRef, while enforcing a gated, memory-resumable migration pipeline. - Both plugins update documentation, plugin registries, and skill references to support reliable, repeatable enterprise-scale React migrations.
87 lines
2.4 KiB
Markdown
87 lines
2.4 KiB
Markdown
# flushSync Guide
|
|
|
|
## Import
|
|
|
|
```jsx
|
|
import { flushSync } from 'react-dom';
|
|
// NOT from 'react' - it lives in react-dom
|
|
```
|
|
|
|
If the file already imports from `react-dom`:
|
|
|
|
```jsx
|
|
import ReactDOM from 'react-dom';
|
|
// Add named import:
|
|
import ReactDOM, { flushSync } from 'react-dom';
|
|
```
|
|
|
|
## Syntax
|
|
|
|
```jsx
|
|
flushSync(() => {
|
|
this.setState({ ... });
|
|
});
|
|
// After this line, the re-render has completed synchronously
|
|
```
|
|
|
|
Multiple setState calls inside one flushSync batch together into ONE synchronous render:
|
|
|
|
```jsx
|
|
flushSync(() => {
|
|
this.setState({ step: 'loading' });
|
|
this.setState({ progress: 0 });
|
|
// These batch together → one render
|
|
});
|
|
```
|
|
|
|
## When to Use
|
|
|
|
✅ Use when the user must see a specific UI state BEFORE an async operation starts:
|
|
|
|
```jsx
|
|
flushSync(() => this.setState({ loading: true }));
|
|
await expensiveAsyncOperation();
|
|
```
|
|
|
|
✅ Use in multi-step progress flows where each step must visually complete before the next:
|
|
|
|
```jsx
|
|
flushSync(() => this.setState({ status: 'validating' }));
|
|
await validate();
|
|
flushSync(() => this.setState({ status: 'processing' }));
|
|
await process();
|
|
```
|
|
|
|
✅ Use in tests that must assert an intermediate UI state synchronously (avoid when possible - prefer `waitFor`).
|
|
|
|
## When NOT to Use
|
|
|
|
❌ Don't use it to "fix" a reading-this.state-after-await bug - that's Category A (refactor instead):
|
|
|
|
```jsx
|
|
// WRONG - flushSync doesn't fix this
|
|
flushSync(() => this.setState({ loading: true }));
|
|
const data = await fetchData();
|
|
if (this.state.loading) { ... } // still a race condition
|
|
```
|
|
|
|
❌ Don't use it for every setState to "be safe" - it defeats React 18 concurrent rendering:
|
|
|
|
```jsx
|
|
// WRONG - excessive flushSync
|
|
async handleClick() {
|
|
flushSync(() => this.setState({ clicked: true })); // unnecessary
|
|
flushSync(() => this.setState({ processing: true })); // unnecessary
|
|
const result = await doWork();
|
|
flushSync(() => this.setState({ result, done: true })); // unnecessary
|
|
}
|
|
```
|
|
|
|
❌ Don't use it inside a `useEffect` or `componentDidMount` to trigger immediate state - it causes nested render cycles.
|
|
|
|
## Performance Note
|
|
|
|
`flushSync` forces a synchronous render, which blocks the browser thread until the render completes. On slow devices or complex component trees, multiple `flushSync` calls in an async method will cause visible jank. Use sparingly.
|
|
|
|
If you find yourself adding more than 2 `flushSync` calls to a single method, reconsider whether the component's state model needs redesign.
|