I'm trying to learn rehydration of dom using preact. For some unknown reason, the render
function isn't replacing the original DOM node but rather appending to it.
https://github.com/preactjs/preact/issues/24, The 3rd parameter of render
should afford the opportunity to replace:
render(<App />, into, into.lastChild);
https://codesandbox.io/s/beautiful-leavitt-rkwlw?file=/index.html:0-1842
Question: Any ideas on how I can ensure that hydration works as one would expect it to e.g. replace the static counter with the interactive one?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
</head>
<body>
<script>
window.__STATE__ = { components: {} };
</script>
<main>
<div>
<script data-cmp-id="1">
window.__STATE__.components[1] = {
name: "Counter",
props: { id: 1 }
};
</script>
<div>HOW MANY LIKES 0</div>
<button>Increment</button>
</div>
</main>
<script type="module">
import {
html,
useState,
render
} from "https://unpkg.com/htm/preact/standalone.module.js";
let id = 0;
export const withHydration = Component => props => {
id += 1;
return html`
<${Component} ...${props} />
`;
};
const Counter = () => {
const [likes, setLikes] = useState(0);
const handleClick = e => {
e.preventDefault();
setLikes(likes + 1);
};
return html`
<div>HOW MANY LIKES ${likes}</div>
<button onClick=${handleClick}>Increment</button>
`;
};
const componentMap = {
Counter: withHydration(Counter)
};
const $componentMarkers = document.querySelectorAll(`[data-cmp-id]`);
Array.from($componentMarkers).forEach($marker => {
debugger;
const $component = $marker.nextElementSibling;
const { name, props } = window.__STATE__.components[
$marker.dataset.cmpId
];
const Component = componentMap[name];
render(
html`
<${Component} ...${props} />
`,
$component.parentNode,
$component
);
});
</script>
</body>
</html>
All of this is inspired by https://github.com/maoberlehner/eleventy-preact repo.