From 61ea255212864c9b1279cffb9f3a1561cccfc5e3 Mon Sep 17 00:00:00 2001 From: Akshay Ashok Date: Wed, 10 Sep 2025 23:34:11 +0530 Subject: [PATCH 1/5] docs: add flushSync Troubleshooting section --- src/content/reference/react-dom/flushSync.md | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index e23ef4eac77..861e88b5309 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -131,3 +131,57 @@ Without `flushSync`, the print dialog will display `isPrinting` as "no". This is Most of the time, `flushSync` can be avoided, so use `flushSync` as a last resort. + +--- + +## Troubleshooting {/*troubleshooting*/} + +### I'm getting an error: "flushSync was called from inside a lifecycle method" {/*im-getting-an-error-flushsync-was-called-from-inside-a-lifecycle-method*/} + +You might get an error that says: `flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.` + +This happens when you call `flushSync` while React is already rendering, such as inside: + +- Class component lifecycle methods (`componentDidMount`, `componentDidUpdate`, etc.) +- `useLayoutEffect` or `useEffect` hooks +- During the render phase of a component + +```js {1-2,4-6} +import { useEffect } from 'react'; +import { flushSync } from 'react-dom'; + +function MyComponent() { + useEffect(() => { + // 🚩 Wrong: calling flushSync inside an effect + flushSync(() => { + setSomething(newValue); + }); + }, []); + + return
{/* ... */}
; +} +``` + +To fix this, move the `flushSync` call outside of the rendering cycle: + +```js {3-7} +useEffect(() => { + // ✅ Correct: defer flushSync to a microtask + queueMicrotask(() => { + flushSync(() => { + setSomething(newValue); + }); + }); +}, []); +``` + +Or move the `flushSync` call to an event handler: + +```js {2-6} +function handleClick() { + // ✅ Correct: flushSync in event handlers is safe + flushSync(() => { + setSomething(newValue); + }); +} +``` From c27e7174d93ca2b2ebbc44cebf5df7ef975f4116 Mon Sep 17 00:00:00 2001 From: Ricky Date: Thu, 11 Sep 2025 09:58:19 -0400 Subject: [PATCH 2/5] Update src/content/reference/react-dom/flushSync.md --- src/content/reference/react-dom/flushSync.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index 861e88b5309..ee49cc38a40 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -138,14 +138,23 @@ Most of the time, `flushSync` can be avoided, so use `flushSync` as a last resor ### I'm getting an error: "flushSync was called from inside a lifecycle method" {/*im-getting-an-error-flushsync-was-called-from-inside-a-lifecycle-method*/} -You might get an error that says: `flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.` -This happens when you call `flushSync` while React is already rendering, such as inside: +React cannot `flushSync` in the middle of a render. If you call `flushSync` in render, it will noop and you'll see a warning: + + + +Warning: flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task. + + + +This can happen when you call `flushSync` inside: - Class component lifecycle methods (`componentDidMount`, `componentDidUpdate`, etc.) - `useLayoutEffect` or `useEffect` hooks - During the render phase of a component +For example, if you call `flushSync` in an Effect: + ```js {1-2,4-6} import { useEffect } from 'react'; import { flushSync } from 'react-dom'; From cb084e56918d2e2f181c2d315b3660ee31f2e2cf Mon Sep 17 00:00:00 2001 From: Ricky Date: Thu, 11 Sep 2025 09:59:04 -0400 Subject: [PATCH 3/5] oops --- src/content/reference/react-dom/flushSync.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index ee49cc38a40..43ad0da33da 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -145,7 +145,7 @@ React cannot `flushSync` in the middle of a render. If you call `flushSync` in r Warning: flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task. - + This can happen when you call `flushSync` inside: From 812e7e8e282c4471d3c1c6bd3dc9bb033c104387 Mon Sep 17 00:00:00 2001 From: Ricky Date: Thu, 11 Sep 2025 10:11:00 -0400 Subject: [PATCH 4/5] Apply suggestions from code review --- src/content/reference/react-dom/flushSync.md | 35 ++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index 43ad0da33da..e4b9ca83ed9 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -139,7 +139,7 @@ Most of the time, `flushSync` can be avoided, so use `flushSync` as a last resor ### I'm getting an error: "flushSync was called from inside a lifecycle method" {/*im-getting-an-error-flushsync-was-called-from-inside-a-lifecycle-method*/} -React cannot `flushSync` in the middle of a render. If you call `flushSync` in render, it will noop and you'll see a warning: +React cannot `flushSync` in the middle of a render. If you do, it will noop and warn: @@ -147,13 +147,13 @@ Warning: flushSync was called from inside a lifecycle method. React cannot flush -This can happen when you call `flushSync` inside: +This includes calling `flushSync` inside: -- Class component lifecycle methods (`componentDidMount`, `componentDidUpdate`, etc.) -- `useLayoutEffect` or `useEffect` hooks -- During the render phase of a component +- During the render phase of a component. +- `useLayoutEffect` or `useEffect` hooks. +- Class component lifecycle methods. -For example, if you call `flushSync` in an Effect: +For example, calling `flushSync` in an Effect will noop and warn: ```js {1-2,4-6} import { useEffect } from 'react'; @@ -171,7 +171,18 @@ function MyComponent() { } ``` -To fix this, move the `flushSync` call outside of the rendering cycle: +To fix this, you usually want to move the `flushSync` call to an event: + +```js {2-6} +function handleClick() { + // ✅ Correct: flushSync in event handlers is safe + flushSync(() => { + setSomething(newValue); + }); +} + + +If it's difficult to move to an event, you can move the flush outside render using a microtask: ```js {3-7} useEffect(() => { @@ -182,15 +193,5 @@ useEffect(() => { }); }); }, []); -``` - -Or move the `flushSync` call to an event handler: -```js {2-6} -function handleClick() { - // ✅ Correct: flushSync in event handlers is safe - flushSync(() => { - setSomething(newValue); - }); -} ``` From 1c4a0ddf07f007de76ff466094541cd4987d5ff2 Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Thu, 11 Sep 2025 10:31:03 -0400 Subject: [PATCH 5/5] formatting and pitfall --- src/content/reference/react-dom/flushSync.md | 22 +++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index e4b9ca83ed9..6fe53337d44 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -149,13 +149,13 @@ Warning: flushSync was called from inside a lifecycle method. React cannot flush This includes calling `flushSync` inside: -- During the render phase of a component. +- rendering a component. - `useLayoutEffect` or `useEffect` hooks. - Class component lifecycle methods. -For example, calling `flushSync` in an Effect will noop and warn: +For example, calling `flushSync` in an Effect will noop and warn: -```js {1-2,4-6} +```js import { useEffect } from 'react'; import { flushSync } from 'react-dom'; @@ -173,18 +173,19 @@ function MyComponent() { To fix this, you usually want to move the `flushSync` call to an event: -```js {2-6} +```js function handleClick() { // ✅ Correct: flushSync in event handlers is safe flushSync(() => { setSomething(newValue); }); } +``` -If it's difficult to move to an event, you can move the flush outside render using a microtask: +If it's difficult to move to an event, you can defer `flushSync` in a microtask: -```js {3-7} +```js {3,7} useEffect(() => { // ✅ Correct: defer flushSync to a microtask queueMicrotask(() => { @@ -193,5 +194,12 @@ useEffect(() => { }); }); }, []); - ``` + +This will allow the current render to finish and schedule another syncronous render to flush the updates. + + + +`flushSync` can significantly hurt performance, but this particular pattern is even worse for performance. Exhaust all other options before calling `flushSync` in a microtask as an escape hatch. + +