preactjs/preact-custom-element

Hydration with shadow root doesn't work

Open

#52 创建于 2020年9月21日

在 GitHub 查看
 (2 评论) (0 反应) (0 负责人)JavaScript (54 fork)github user discovery
help wanted

仓库指标

Star
 (402 star)
PR 合并指标
 (PR 指标待抓取)

描述

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>

贡献者指南