fix(web): initialize SkiaPictureView renderer from a layout effect#3830
Open
svavarstudio wants to merge 1 commit intoShopify:mainfrom
Open
fix(web): initialize SkiaPictureView renderer from a layout effect#3830svavarstudio wants to merge 1 commit intoShopify:mainfrom
svavarstudio wants to merge 1 commit intoShopify:mainfrom
Conversation
Platform.View's onLayout (driven by react-native-web's ResizeObserver shim) does not always fire before the first picture is dispatched, leaving renderer.current === null while the tick loop drains redrawRequests without ever painting. Initialize the WebGL renderer from a useLayoutEffect as soon as the <canvas> ref has measurable layout, with a bounded rAF retry. Guard onLayoutEvent so it does not clobber an already-constructed renderer.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3829.
Problem
SkiaPictureView.web.tsxonly constructs itsWebGLRendererinsideonLayoutEvent, which is wired to the wrapperPlatform.View'sonLayout(driven by react-native-web'sResizeObservershim). In several real-world layouts that callback does not fire before the first picture is dispatched, leavingrenderer.current === null. ThetickrAF loop then drainsredrawRequestsRefindefinitely without ever painting, and the canvas stays transparent. Repro and root-cause logging are in #3829.Fix
Add a
useLayoutEffectthat initializes the renderer as soon as the<canvas>ref has measurable dimensions. If the canvas hasn't been laid out yet, retry onrequestAnimationFrame(bounded to ~600 frames). GuardonLayoutEventso it doesn't clobber an already-constructed renderer (it remains responsible for the resize path).This is purely additive —
onLayoutEventstill runs first when its event reliably fires, and the new effect is a no-op in that case (early-returns onrenderer.current).Risk / compatibility
onLayoutalready fires reliably, the new effect is a no-op.SkiaPictureView.tsx) is unaffected — only the.web.tsxentry is touched.Test plan
Manually verified in an Expo + react-native-web app (Chrome 124, Firefox 125, Safari 17) that a
<Canvas>inside a flex column with an absolutely-positioned sibling now paints on first commit. Existing web tests inpackages/skia/__tests__still pass locally.