UNPKG

1.74 kBJavaScriptView Raw
1import { h, createContext } from "preact";
2import { useContext } from "preact/hooks";
3import { Buffer } from "buffer";
4import { __DocContext } from "./document";
5const isServer = typeof window === "undefined";
6const btoa = (str) => Buffer.from(str, "utf-8").toString("base64");
7const HydrateContext = createContext(false);
8export function withHydrate(Component, hydrationProps = {}) {
9 const name = Component.displayName || Component.name;
10 const { method = "idle" } = hydrationProps;
11 const Wrapped = (props, ref) => {
12 const { hydrate } = useContext(__DocContext);
13 const hydrateParent = useContext(HydrateContext);
14 if (hydrateParent)
15 throw new Error(`withHydrate() should only be called at the top-level of a Component tree. <${name} /> should not be nested within <${hydrateParent} />`);
16 if (isServer)
17 hydrate.current.push({ name });
18 if (props.children && !["string", "number"].includes(typeof props.children))
19 throw new Error(`withHydrate() is unable to serialize complex \`children\`. Please inline these children into <${name} />.`);
20 return (h(HydrateContext.Provider, { value: name },
21 h("div", Object.assign({}, (isServer
22 ? {
23 "data-hydrate": name,
24 "data-props": Object.keys(props).length > 0
25 ? btoa(JSON.stringify(props))
26 : null,
27 "data-method": method,
28 }
29 : {})),
30 h(Component, Object.assign({}, Object.assign(Object.assign({}, props), { ref }))))));
31 };
32 Object.defineProperty(Wrapped, "name", { value: name, configurable: true });
33 return Wrapped;
34}