What runs on the server
When renderToString, renderToStringAsync or renderToStream render a component, the component body runs, memos compute, and onCleanup callbacks run when the…
When renderToString, renderToStringAsync or renderToStream render a component, the component body runs, memos compute, and onCleanup callbacks run when the render ends. useEffect, useRenderEffect and onMount do nothing: no node is created and the function is never called. Code that touches window, document or timers belongs in those three, not in the component body.
src/server-order.tsxtsx
import { onCleanup, onMount, useEffect, useMemo, useRenderEffect, useStore } from "@shadow-js/core";
import { renderToString } from "@shadow-js/web/server";
const log: string[] = [];
function App() {
const [n] = useStore(1);
const doubled = useMemo(() => {
log.push("memo");
return n() * 2;
});
useEffect(() => {
log.push("effect");
});
useRenderEffect(() => {
log.push("render effect");
});
onMount(() => {
log.push("mount");
});
onCleanup(() => {
log.push("cleanup");
});
log.push("body");
return <p>{doubled()}</p>;
}
renderToString(() => <App />);
console.log(log.join(","));
memo,body,cleanupOn the client the same component renders again (or is hydrated) and its effects run after the first flush. See SSR, hydration and streaming.