Skip to content

Instantly share code, notes, and snippets.

@ka2n
Created February 25, 2021 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ka2n/f4007bbc60b31fb7f240a3d51372acdb to your computer and use it in GitHub Desktop.
Save ka2n/f4007bbc60b31fb7f240a3d51372acdb to your computer and use it in GitHub Desktop.
Hydrate from Javascript
/// <reference types="requestidlecallback-polyfill" />
import React, { createElement, useEffect, useState } from "react"
if (typeof window !== "undefined") {
require("requestidlecallback-polyfill")
}
const components = {
Test: () => {
return <div>Hello!</div>
},
}
const Page = () => {
const jsxSource = {
compiledSource: `
function HTMLContent() { return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, "Hello"), /*#__PURE__*/React.createElement(Test, null)) }
`,
renderedOutput: `
<p>Hello</p>
<div>Hello!!</div>
`,
}
const content = hydrate(jsxSource)
return (
<div>
<h1>Hello</h1>
<div>{content}</div>
</div>
)
}
function hydrate(source: { compiledSource: string; renderedOutput: string }) {
const [result, setResult] = useState<React.ReactElement>(
// 初期値はサーバサイドでレンダリングしたHTML
createElement("div", {
dangerouslySetInnerHTML: {
__html: source.renderedOutput,
},
})
)
useEffect(() => {
const handler = window.requestIdleCallback(() => {
const scope = { ...components }
const hydrateFn = Reflect.construct(Function, [
"React",
...Object.keys(scope),
source.compiledSource + "\nreturn React.createElement(HTMLContent)",
])
const hydrated = hydrateFn.apply(hydrateFn, [
React,
...Object.values(scope),
])
setResult(hydrated)
window.cancelIdleCallback(handler)
})
return () => window.cancelIdleCallback(handler)
}, [source.compiledSource])
return result
}
export default Page
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment