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
Blankeos4w ago
Reddit
From the solidjs community on Reddit
Explore this post and more from the solidjs community
REEEEE
REEEEE4w 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
mdynnl4w 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
Blankeos4w 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
mdynnl4w ago
yeah, i was looking at an old thread related to inertia layouts and that slipped in
Blankeos
Blankeos4w 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
Blankeos4w ago
This is what I wrote so far
No description
mdynnl
mdynnl4w 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
Blankeos4w ago
Interesting! Thanks for this.
mdynnl
mdynnl4w ago
it needs some elements for hydration marker the logic acutally comes from MultiProvider
context: https://discord.com/channels/722131463138705510/1108166822286602361/1108504704201277451
Blankeos
Blankeos4w ago
Ah man.. Just tried it, unfortunately still doesn't work. I also don't have fragments for the layouts.
No description
mdynnl
mdynnl4w 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
Blankeos3w ago
Thanks bud. Was able to solve it thanks to the links!
Want results from more Discord servers?
Add your server
More Posts