How do I recursively wrap a `JSX.Element` with an `Array<FlowComponent>`

// Let's say we have these values:
const children = props.children
const layouts = [Layout1, Layout2, Layout3];


// How do I turn it into:
return (
<Layout1>
<Layout2>
<Layout3>
{props.children}
</Layout3>
</Layout2>
</Layout>
);
// Let's say we have these values:
const children = props.children
const layouts = [Layout1, Layout2, Layout3];


// How do I turn it into:
return (
<Layout1>
<Layout2>
<Layout3>
{props.children}
</Layout3>
</Layout2>
</Layout>
);
I think turning it into this is fine. But keeping the reactivity is a little challenging.
13 Replies
Blankeos
BlankeosOP7mo ago
Reddit
From the solidjs community on Reddit
Explore this post and more from the solidjs community
REEEEE
REEEEE7mo ago
GitHub
solid-primitives/packages/context/src/index.ts at 8e6089531dea15947...
A library of high-quality primitives that extend SolidJS reactivity. - solidjs-community/solid-primitives
mdynnl
mdynnl7mo ago
MultiProvider doesn't take into account that the values can change, so you might need to wrap with createMemo or use <>{render(0)}</>
Blankeos
BlankeosOP7mo ago
Thanks @REEEEE ! It seemed to work but I'm getting hydration issues. (Essentially the backend rendered my component differently, and the frontend also rendered it differently). Maybe because for my case, I'm rendering UI as well (other than context). Wondering if @mdynnl 's solution would work. Can you elaborate on using createMemo here? Also, render(0), do you mean the fn(0) used in the MultiProvider example?
mdynnl
mdynnl7mo ago
yeah, i was looking at an old thread related to inertia layouts and that slipped in
Blankeos
BlankeosOP7mo ago
Btw for context, I'm trying to code Vike's SSR for rendering cumulative layouts atm. Basically, there's a layouts: FlowComponent[] and a children: JSX.Element. I'm trying to wrap children with a bunch of layouts essentially. I tried doing your solution but no luck
Blankeos
BlankeosOP7mo ago
This is what I wrote so far
No description
mdynnl
mdynnl7mo ago
import { ParentComponent, ParentProps } from "solid-js";

function Layouts(p: ParentProps<{ layouts?: ParentComponent[] }>) {
function render(i: number) {
const Layout = (p.layouts ?? [])[i];
if (!Layout) {
return p.children;
}
return <Layout children={render(i + 1)} />; // same as createComponent
}

return <>{render(0)}</>;
}

export default function Home() {
return (
<div>
hello
<Layouts
layouts={[
(p) => <div>a{p.children}</div>,
(p) => <div>b{p.children}</div>,
(p) => <>c{p.children}</>,
]}
children={"world"}
/>
</div>
);
}
import { ParentComponent, ParentProps } from "solid-js";

function Layouts(p: ParentProps<{ layouts?: ParentComponent[] }>) {
function render(i: number) {
const Layout = (p.layouts ?? [])[i];
if (!Layout) {
return p.children;
}
return <Layout children={render(i + 1)} />; // same as createComponent
}

return <>{render(0)}</>;
}

export default function Home() {
return (
<div>
hello
<Layouts
layouts={[
(p) => <div>a{p.children}</div>,
(p) => <div>b{p.children}</div>,
(p) => <>c{p.children}</>,
]}
children={"world"}
/>
</div>
);
}
i think soid-js need better hydration strategy can't have adjacent fragment layouts
Blankeos
BlankeosOP7mo ago
Interesting! Thanks for this.
mdynnl
mdynnl7mo ago
it needs some elements for hydration marker the logic acutally comes from MultiProvider
context: https://discord.com/channels/722131463138705510/1108166822286602361/1108504704201277451
Blankeos
BlankeosOP7mo ago
Ah man.. Just tried it, unfortunately still doesn't work. I also don't have fragments for the layouts.
No description
mdynnl
mdynnl7mo ago
import {
onMount,
type JSX,
type ParentComponent,
type ParentProps,
} from "solid-js";

function Layouts(props: ParentProps<{ layouts?: ParentComponent[] }>) {
return (() => render(0)) as unknown as JSX.Element; // use at your own risk
function render(i: number) {
const { layouts } = props;
if (layouts) {
const Layout = layouts[i];
if (Layout) {
return <Layout>{render(i + 1)}</Layout>;
}
}
return props.children;
}
}

import { createStore } from "solid-js/store";

export default function Test() {
const [layouts, setLayouts] = createStore([
(p) => <>a:{p.children}</>,
(p) => <>b:{p.children}</>,
] as ParentComponent[]);

onMount(() => setTimeout(() => setLayouts([]), 1000));

return <Layouts layouts={layouts}>world</Layouts>;
}
import {
onMount,
type JSX,
type ParentComponent,
type ParentProps,
} from "solid-js";

function Layouts(props: ParentProps<{ layouts?: ParentComponent[] }>) {
return (() => render(0)) as unknown as JSX.Element; // use at your own risk
function render(i: number) {
const { layouts } = props;
if (layouts) {
const Layout = layouts[i];
if (Layout) {
return <Layout>{render(i + 1)}</Layout>;
}
}
return props.children;
}
}

import { createStore } from "solid-js/store";

export default function Test() {
const [layouts, setLayouts] = createStore([
(p) => <>a:{p.children}</>,
(p) => <>b:{p.children}</>,
] as ParentComponent[]);

onMount(() => setTimeout(() => setLayouts([]), 1000));

return <Layouts layouts={layouts}>world</Layouts>;
}
https://stackblitz.com/edit/938r3a?file=pages%2Findex%2F%2BPage.tsx
Blankeos
BlankeosOP7mo ago
Thanks bud. Was able to solve it thanks to the links!
Want results from more Discord servers?
Add your server