-
Notifications
You must be signed in to change notification settings - Fork 50.3k
Description
React version: 18
When a state value gets updated in a ResizeObserver callback, I believe that React should make sure that the DOM is up-to-date before the next paint. Otherwise, if we are using ResizeObserver to do some visual changes to some part(s) of the app as soon as some element resizes (which seems like a reasonable assumption), it can create visual glitches.
It worked fine in React 17, but in React 18 the state updates seem to be deferred to a later time (unless flushSync is used). This is most likely due to the "batch state updates" change in React 18.
Steps To Reproduce
In the example below we use a ResizeObserver to make sure that the width of the blue div always matches exactly the width of the grey textarea under it.
- Quickly resize the grey textarea. Notice that the width of the blue div lags behind.
- Turn on the
shouldUseFlushSyncflag in the code and quickly resize the grey textarea again. Notice that they now stay perfectly in sync, the glitch is gone.
Link to code example: https://codesandbox.io/s/amazing-montalcini-j6lz46?file=/src/App.js (tested in Chrome on Linux)
(it is probably more visible on a slow computer, you can try enabling CPU throttling if you cannot see it)
The current behavior
We need to use flushSync in order for the app to work without glitches.
The expected behavior
Given that it is probably pretty common to use ResizeObserver to make sure that some part of the app stays visually in sync with some other part of the app, I would expect React to guarantee that updates triggered in a ResizeObserver callback will be applied before the browser gets the chance to paint the resized element, and without expecting the developer to use the somewhat obscure flushSync method.
Related
I could only find one related issue: #21119, but it is about batching several updates coming from the same callback. It's perfectly fine to batch several updates coming from the same ResizeObserver callback (or even from several such) as long as they are guaranteed to be applied before the resized element is painted again by the browser.