Repository navigation
fix: measure a window resize on web once for every provider - #788
YevheniiKotyrlo wants to merge 3 commits into
Conversation
…ze event The resize listener ran before the frame's layout, so reading the provider element's rect there forced a synchronous layout, and when the provider resized with the window its ResizeObserver reported the same values again once layout had run. The context element now spans the viewport and the same observer watches it, so a window resize is measured once, after layout. Without a ResizeObserver the provider keeps the window resize listener.
|
@YevheniiKotyrlo is attempting to deploy a commit to the appandflow Team on Vercel. A member of the Team first needs to authorize it. |
…rve a border box Chrome before 84 and Safari before 15.4 ignore the box option and observe the content box, which the context element's env() padding transition resizes, so those engines would report the insets at every step of the transition. They keep the window resize listener, as an engine without ResizeObserver does.
Measurements — before / afterUNFIXED — Over a 190-step window resize, two nested providers commit React 570 times, three per step: once in each provider's FIXED — 191 commits, one per step and one more, from a single window
Chromium 153, Firefox 155 and WebKit 26.6, two runs each, read the same. Two nested |
…changes Measuring a window resize from a ResizeObserver alone painted the new metrics a frame after the resize, because React commits an update made in an observer callback after paint, and it missed a resize that only moves the provider once a transform on body narrowed the viewport-spanning context element. The resize event stays where a window resize is measured. One listener measures every provider, so React commits their updates together, and a provider reports only metrics that changed, as the native providers do, so the ResizeObserver callback that follows a resize commits nothing.
Summary
On web, every
SafeAreaProvidermeasures a window resize from aresizelistener of its own, and React commits the updates made in each listener separately, so nested providers commit once each per resize step. Each provider'sResizeObserverthen measures again after layout and reports the values its listener already reported, which React renders once more. Two nested providers, as an Expo Router app mounts them beside an app shell's own provider, commit three times per step.One
resizelistener now measures every provider, so React commits their updates together, and a provider reports only metrics that changed, as the Android and iOS providers do, so the observer callback that follows a resize commits nothing. The measurement stays in theresizeevent, so a provider that only moves is still measured and the new metrics still paint in the resize's own frame.Test Plan
NativeSafeAreaProvider.web-test.tsx: "measures nested providers from one window resize listener" and "does not report metrics that did not change" fail onmainand pass here. "measures a window resize that moves the provider without resizing it" and "reports a window resize that changes the insets and leaves the frame as it was" hold theresize-event measurement for a provider that only moves and for an insets-only change.format:spotless:check).