Wildhoney / ReactShadow

:beginner: Utilise Shadow DOM in React with all the benefits of style encapsulation.
https://react-shadow.herokuapp.com/
MIT License
1.29k stars 80 forks source link

Attach shadow root in layout effect to avoid layout shift #145

Closed georgeclaghorn closed 1 year ago

georgeclaghorn commented 1 year ago

ShadowRoot attaches and populates the shadow DOM tree in a useEffect callback. useEffect callbacks are invoked asynchronously after React populates the DOM. It’s possible for the browser to repaint after React initially adds a ShadowRoot’s <options.tag> element to the DOM but before it invokes the useEffect callback. When this happens, the shadow DOM’s contents may be noticeably delayed in appearing on screen. In my case, loading relatively complex HTML into a shadow DOM tree, its contents take about 130ms to appear (in latest Safari on latest macOS on a 2020 M1 MacBook Pro). This causes undesirable layout shift—the other content on the page gets pushed around as shadow DOM contents load.

For this reason, React provides an alternative hook, useLayoutEffect. Callbacks provided to useLayoutEffect are invoked synchronously after React updates the DOM and before the next paint. Replacing useEffect with useLayoutEffect in ShadowRoot eliminates the delay in shadow DOM contents appearing on screen and the resulting layout shift for me.

Wildhoney commented 1 year ago

Thanks @georgeclaghorn 👍