-
Notifications
You must be signed in to change notification settings - Fork 53
Description
If you register a component as a custom element with { shadow: true }
then the code in the connectedCallback will try to run the hydrate function with the shadow root as the target node. This ends up rendering the entire component inside the shadow root while preserving, but not rendering, existing children (perhaps they're being treated like slot contents?) outside the shadow root which defeats the purpose of hydration.
I found this out while testing SSR with shadow root; I know you can't declaratively add a shadow root. But I was wondering if moving existing children of the custom element into the shadow root then attempting to hydrate would work? Is there risk of content reflow or style flashing? Is this simply just a limitation of custom elements that cannot be circumvented and therefore not in scope here?
Here's an example:
import { h, Fragment } from 'preact';
import { useState } from 'preact/hooks'
import register from 'preact-custom-element';
export const Counter = ({increment}) => {
let [ count, setCount ] = useState(0)
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount(count + Number(increment))}>Increment by: {increment}</button>
<button onClick={() => setCount(count - Number(increment))}>Decrement by: {increment}</button>
<slot />
</>
)
}
register(Counter, 'my-counter', ['increment'], { shadow: true })
<my-counter increment="5" hydrate>
<p>Count: 0</p>
<button>Increment by: 5</button>
<button>Decrement by: 5</button>
</my-counter>
These are the results when the script loads:
<my-counter increment="5" hydrate>
#shadow-root
<p>Count: 0</p>
<button>Increment by: 5</button>
<button>Decrement by: 5</button>
<p>Count: 0</p>
<button>Increment by: 5</button>
<button>Decrement by: 5</button>
</my-counter>
This would be the desired results:
<my-counter increment="5" hydrate>
#shadow-root
<p>Count: 0</p>
<button>Increment by: 5</button>
<button>Decrement by: 5</button>
</my-counter>