diff --git a/examples/ssr/shared/src/components/Home.js b/examples/ssr/shared/src/components/Home.js index 55bd3d68..2ab214f3 100644 --- a/examples/ssr/shared/src/components/Home.js +++ b/examples/ssr/shared/src/components/Home.js @@ -1,22 +1,28 @@ -import { createSignal, onSettled } from "solid-js"; +import { createSignal, Errored, Loading, onSettled } from "solid-js"; const Home = () => { - const [s, set] = createSignal(0); - onSettled(() => { - const t = setInterval(() => { - const newVal = s() + 1; - set(newVal); - }, 100); - return () => { - clearInterval(t); - }; - }); + const [count, setCount] = createSignal(0); + const props = { + test: "test", + test2: "test2" + }; return ( - <> -

Welcome to this Simple Routing Example

-

Click the links in the Navigation above to load different routes.

- {s()} - +
+ + +
); }; +function Link(props) { + const linkProps = { + href: "/", + onClick: e => { + e.preventDefault(); + console.log("clicked", props.count); + } + }; + + return My Link {props.count}; +} + export default Home; diff --git a/examples/ssr/stream/rollup.config.js b/examples/ssr/stream/rollup.config.js index 7a65bc03..ce60f09b 100644 --- a/examples/ssr/stream/rollup.config.js +++ b/examples/ssr/stream/rollup.config.js @@ -55,7 +55,7 @@ export default [ nodeResolve({ preferBuiltins: true, exportConditions: ["solid", "node"] }), babel({ babelHelpers: "bundled", - presets: [["solid", { generate: "ssr", hydratable: true }]] + presets: [["solid", { generate: "ssr", hydratable: true, dev: true }]] }), common() ] @@ -70,10 +70,10 @@ export default [ ], preserveEntrySignatures: false, plugins: [ - nodeResolve({ exportConditions: ["solid"] }), + nodeResolve({ exportConditions: ["solid", "development"] }), babel({ babelHelpers: "bundled", - presets: [["solid", { generate: "dom", hydratable: true }]] + presets: [["solid", { generate: "dom", hydratable: true, dev: true }]] }), common(), solidAssetManifest(), diff --git a/packages/solid/src/index.ts b/packages/solid/src/index.ts index 47e0b60c..6ff852fb 100644 --- a/packages/solid/src/index.ts +++ b/packages/solid/src/index.ts @@ -84,8 +84,8 @@ export { createOptimisticStore } from "./client/hydration.js"; // stub -export function ssrHandleError() {} -export function ssrRunInScope() {} +export function ssrHandleError() { } +export function ssrRunInScope() { } import type { JSX } from "./jsx.js"; type JSXElement = JSX.Element; diff --git a/packages/solid/src/server/flow.ts b/packages/solid/src/server/flow.ts index 8ada441a..3f3ad231 100644 --- a/packages/solid/src/server/flow.ts +++ b/packages/solid/src/server/flow.ts @@ -23,11 +23,14 @@ export function For(props: { keyed?: boolean | ((item: T[number]) => any); children: (item: Accessor, index: Accessor) => U; }) { + const o = getOwner(); const options = "fallback" in props ? { keyed: props.keyed, fallback: () => props.fallback } : { keyed: props.keyed }; - return createMemo(mapArray(() => props.each, props.children, options)) as unknown as JSX.Element; + const result = createMemo(mapArray(() => props.each, props.children, options)); + if (o?.id != null) getNextChildId(o); // match client's insert() render effect when For is a sibling child + return result as unknown as JSX.Element; } /** @@ -41,14 +44,17 @@ export function Repeat(props: { fallback?: JSX.Element; children: ((index: number) => T) | T; }) { + const o = getOwner(); const options: { fallback?: Accessor; from?: Accessor } = "fallback" in props ? { fallback: () => props.fallback } : {}; options.from = () => props.from; - return repeat( + const result = repeat( () => props.count, index => (typeof props.children === "function" ? props.children(index) : props.children), options - ) as unknown as JSX.Element; + ); + if (o?.id != null) getNextChildId(o); // match client's insert() render effect when Repeat is a sibling child + return result as unknown as JSX.Element; } /** @@ -67,6 +73,7 @@ export function Show(props: { if (!props.keyed) getNextChildId(o); // match client's condition memo (non-keyed only) } const valueOwner = createOwner(); // match client's value memo + if (o?.id != null) getNextChildId(o); // match client's insert() render effect when Show is a sibling child return runWithOwner(valueOwner, () => { const when = props.when; if (when) { @@ -91,7 +98,7 @@ export function Switch(props: { fallback?: JSX.Element; children: JSX.Element }) const o = getOwner(); if (o?.id != null) getNextChildId(o); // advance ID counter - return createMemo(() => { + const result = createMemo(() => { let conds: MatchProps | MatchProps[] = chs() as any; if (!Array.isArray(conds)) conds = [conds]; @@ -103,7 +110,9 @@ export function Switch(props: { fallback?: JSX.Element; children: JSX.Element }) } } return props.fallback; - }) as unknown as JSX.Element; + }); + if (o?.id != null) getNextChildId(o); // match client's insert() render effect when Switch is a sibling child + return result as unknown as JSX.Element; } export type MatchProps = { @@ -128,11 +137,14 @@ export function Errored(props: { fallback: JSX.Element | ((err: any, reset: () => void) => JSX.Element); children: JSX.Element; }): JSX.Element { - return createErrorBoundary( + const o = getOwner(); + const result = createErrorBoundary( () => props.children, (err, reset) => { const f = props.fallback; return typeof f === "function" && f.length ? f(err, reset) : f; } - ) as unknown as JSX.Element; + ); + if (o?.id != null) getNextChildId(o); // match client's insert() render effect when Errored is a sibling child + return result as unknown as JSX.Element; } diff --git a/packages/solid/src/server/hydration.ts b/packages/solid/src/server/hydration.ts index 3af7c35a..67a6a084 100644 --- a/packages/solid/src/server/hydration.ts +++ b/packages/solid/src/server/hydration.ts @@ -1,5 +1,6 @@ import { createOwner, + getOwner, getNextChildId, runWithOwner, createLoadBoundary, @@ -49,9 +50,11 @@ export function Loading(props: { fallback?: JSX.Element; children: JSX.Element } ) as unknown as JSX.Element; } + const parent = getOwner(); const o = createOwner(); const id = o.id!; (o as any).id = id + "00"; // fake depth to match client's createLoadBoundary nesting + if (parent?.id != null) getNextChildId(parent); // match client's insert() render effect when Loading is a sibling child let runPromise: Promise | undefined; let serializeBuffer: [string, any, boolean?][] = []; diff --git a/packages/solid/src/server/index.ts b/packages/solid/src/server/index.ts index 7e5de8fd..b3471cfc 100644 --- a/packages/solid/src/server/index.ts +++ b/packages/solid/src/server/index.ts @@ -70,7 +70,13 @@ export type { } from "./signals.js"; // Wrappers — context, children, dev symbols -export { $DEVCOMP, children, createContext, useContext, ssrRunInScope } from "./core.js"; +export { + $DEVCOMP, + children, + createContext, + useContext, + ssrRunInScope +} from "./core.js"; export type { ChildrenReturn, Context,