S
SolidJS•13mo ago
Mirardes

Dynamic Component is not working

Hi, I try to use Dynamic component without success. I have try to replicate the issue in playground and the bug is still present : Playground : https://playground.solidjs.com/anonymous/83f1450a-6060-4ae1-8361-b6436402949b
import { Dynamic, render } from "solid-js/web";
import { createEffect, createSignal } from "solid-js";

export const StepperLayout = (props) => {
console.log('QWEQWEQWEQE');

return <>STEP LAYOUT {props?.children}</>;
};

export const AppLayout = (props) => {
return <>APP LAYOUT {props?.children}</>;
};


const LayoutHome = (props: { children; currentStep?: string }) => {
const [layout, setLayout] = createSignal(AppLayout);

createEffect(() => {
if (props.currentStep?.startsWith('STEP')) {
setLayout(StepperLayout);
}
});

createEffect(() => {
console.log(layout(), AppLayout);
});

return <Dynamic component={layout()}>{props.children}</Dynamic>;
};

function Counter() {
const [count, setCount] = createSignal(1);
const increment = () => setCount(count() + 1);

return (
<button type="button" onClick={increment}>
{count()}
</button>
);
}

render(() => <><LayoutHome currentStep="STEP">toto</LayoutHome></>, document.getElementById("app")!);
import { Dynamic, render } from "solid-js/web";
import { createEffect, createSignal } from "solid-js";

export const StepperLayout = (props) => {
console.log('QWEQWEQWEQE');

return <>STEP LAYOUT {props?.children}</>;
};

export const AppLayout = (props) => {
return <>APP LAYOUT {props?.children}</>;
};


const LayoutHome = (props: { children; currentStep?: string }) => {
const [layout, setLayout] = createSignal(AppLayout);

createEffect(() => {
if (props.currentStep?.startsWith('STEP')) {
setLayout(StepperLayout);
}
});

createEffect(() => {
console.log(layout(), AppLayout);
});

return <Dynamic component={layout()}>{props.children}</Dynamic>;
};

function Counter() {
const [count, setCount] = createSignal(1);
const increment = () => setCount(count() + 1);

return (
<button type="button" onClick={increment}>
{count()}
</button>
);
}

render(() => <><LayoutHome currentStep="STEP">toto</LayoutHome></>, document.getElementById("app")!);
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
19 Replies
Jasmin
Jasmin•13mo ago
Interesting, if you pass the accessor without calling it, it works but typescript throws an error. <Dynamic component={layout}> Could be a mistake in the type definitions of the Dynamic component ah no this isn't the correct way. I checked the code of <Dynamic> at I'm not sure why this doesn't work thinkies
Mirardes
MirardesOP•13mo ago
Yes me too .... Since 25 minutes i'm struggling to understand maybe ping core team ?
Jasmin
Jasmin•13mo ago
Okay you have to wrap the layout components in a function when using them in the signal. This works: https://playground.solidjs.com/anonymous/b5543d36-5b89-4da9-a1c5-5fe368f88333
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Jasmin
Jasmin•13mo ago
can't explain why tho 🙈
Mirardes
MirardesOP•13mo ago
WTF doesn't make sense Dynamic don't support Accessible *Accessor so it should not work
Jasmin
Jasmin•13mo ago
it supports getters :)
Mirardes
MirardesOP•13mo ago
yes but why with a function return it works and with a value not due to solid-proxy ?
Jasmin
Jasmin•13mo ago
I'm not sure, but would be interested in the explanation @fabiospampinato surely knows whats happening here stare you're probably right. it looks like accessing the signal returns the rendered component
fabiospampinato
fabiospampinato•13mo ago
yeah, if you uncomment the setLayout call both work, though I'm not sure if the one with the signal that returns () => AppLayout actually works
Jasmin
Jasmin•13mo ago
tricky situation you're right, it doesn't work. The initial value has to be createSignal(AppLayout) and you only have to wrap it in a function if you're changing the signal with the setter function https://playground.solidjs.com/anonymous/fc71a309-5ce4-4c2c-9ab5-37a23c8041cf this is the correct solution
Mirardes
MirardesOP•13mo ago
Sorry to be stupid but why in these condition it work only with () => ?
Jasmin
Jasmin•13mo ago
because if you're passing a function to the setter, solid thinks you want to do this:
const newCount = setCount((prev) => prev + 1);
const newCount = setCount((prev) => prev + 1);
and runs this function and uses its return value as the new value for the signal and in your case, the return value is the return value of your layout so we have to wrap it in another function
Mirardes
MirardesOP•13mo ago
so the issue come from how solid identify Functional Component
lxsmnsyc
lxsmnsyc•13mo ago
no. The issue here is that signal setters can either accept the value or the action. action is a function if you pass a function to the setter, the setter thinks you are passing an "action" so it tries to resolve it.
Mirardes
MirardesOP•13mo ago
Okay seems logic
lxsmnsyc
lxsmnsyc•13mo ago
or to simplify
function setSignal(newValue) {
if (typeof newValue === 'function') {
newValue = newValue(currentValue);
}
return updateState(newValue);
}
function setSignal(newValue) {
if (typeof newValue === 'function') {
newValue = newValue(currentValue);
}
return updateState(newValue);
}
Mirardes
MirardesOP•13mo ago
I can close the issue thanks !
Jasmin
Jasmin•13mo ago
yes
Want results from more Discord servers?
Add your server