-
-
Notifications
You must be signed in to change notification settings - Fork 408
feat: add deferFlushSync option for React 19 compatibility
#1098
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add deferFlushSync option for React 19 compatibility
#1098
Conversation
…bility React 19 throws a warning when flushSync is called from inside a lifecycle method (useLayoutEffect). This change defers the flushSync call to a microtask using queueMicrotask(), allowing React to complete its current render cycle before forcing the synchronous update. Fixes the warning: 'flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering.'
🦋 Changeset detectedLatest commit: fa4acc3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@piecyk Hi, could you review this PR please? |
|
@channyeintun Thanks for taking a look at this. Unfortunately, deferring flushSync via queueMicrotask() fundamentally changes the behavior here. In this code path, flushSync is intentionally used to synchronously apply the scroll correction during measurement to limit visible white space while scrolling. By pushing it into a microtask, React has already completed the render/commit phase and the scroll has progressed further, effectively making this flushSync a no-op for its original purpose. In practice this reintroduces the exact issue flushSync was added to solve: noticeable gaps during fast scrolling with dynamic measurements. Instead of changing the default behavior, I think we should make this configurable under a flag in @tanstack/react-virtual. ps: the warning itself doesn’t really affect anything in this case. |
Instead of unconditionally deferring flushSync via queueMicrotask, add a configurable option that allows users to opt-in to this behavior. - Add deferFlushSync option to VirtualizerOptions (default: false) - Update react-virtual to conditionally defer flushSync based on option - Update tests to cover both synchronous (default) and deferred behaviors This addresses reviewer feedback that unconditionally deferring flushSync changes the scroll correction behavior and reintroduces visible gaps during fast scrolling with dynamic measurements. Fixes TanStack#1094
deferFlushSync option for React 19 compatibility
Good call - I didn't consider that deferring breaks the scroll correction. I've changed it to an opt-in flag (deferFlushSync) so the default stays synchronous. Users who hit the warning can enable it if they're okay with the tradeoff. |
React 19 throws a warning when
flushSyncis called from inside a lifecycle method (useLayoutEffect). This change adds a newdeferFlushSyncoption that users can enable to deferflushSyncto a microtask, suppressing the warning.Fixes #1094
🎯 Changes
Problem
When using
@tanstack/react-virtualwith React 19, users see the following warning in the console:This occurs because
flushSync(rerender)is called inside theonChangecallback, which can be triggered duringuseLayoutEffectviainstance._willUpdate().Solution
Added a new
deferFlushSyncoption that users can enable to defer theflushSynccall:When enabled, the
flushSynccall is wrapped inqueueMicrotask():if (sync) { - flushSync(rerender) + if (options.deferFlushSync) { + queueMicrotask(() => flushSync(rerender)) + } else { + flushSync(rerender) + } }Why opt-in instead of default?
flushSyncbehavior is intentional for scroll correction during measurementFiles Changed
packages/virtual-core/src/index.ts- AdddeferFlushSyncoption toVirtualizerOptionspackages/react-virtual/src/index.tsx- Conditionally wrapflushSyncbased on optionpackages/react-virtual/tests/index.test.tsx- Add test fordeferFlushSyncbehavior✅ Checklist
pnpm run test:pr.🚀 Release Impact