S
SolidJS12mo ago
Liquido

How can I set a style based on reactive state with fallback to props?

I want to change color of a button when active and return back to default value when not active:
const Internal = (props) => {
const [clicked, setClicked] = createSignal(false);

const style = mergeProps(props.style, { color: clicked() ? 'orange' : 'red' });

return <button onClick={() => setClicked(c => !c)} style={style}>
{props.children}
</button>
}

function Counter() {
return (
<Internal style={{ color: 'blue', fontWeight: 'bold' }}>Click me</Internal>
);
}
const Internal = (props) => {
const [clicked, setClicked] = createSignal(false);

const style = mergeProps(props.style, { color: clicked() ? 'orange' : 'red' });

return <button onClick={() => setClicked(c => !c)} style={style}>
{props.children}
</button>
}

function Counter() {
return (
<Internal style={{ color: 'blue', fontWeight: 'bold' }}>Click me</Internal>
);
}
https://playground.solidjs.com/anonymous/c98af79a-5755-4edd-a7a4-f91d60c3ae02 How can I make the style value inside the Internal component reactive?
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
5 Replies
apollo79
apollo7912mo ago
The way you have it now, it will call the clicked getter function only once, to have it rerunning, you can change color to be a getter https://playground.solidjs.com/anonymous/de94fa0e-cefd-4f24-8f1e-9351ff5907f6
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Liquido
LiquidoOP12mo ago
I ended up creating creating a function that is called when passing to stykle:
const style = () => mergeProps(props.style, { color: clicked() ? 'orange' : 'red' });

return <button onClick={() => setClicked(c => !c)} style={style()}>
{props.children}
</button>
const style = () => mergeProps(props.style, { color: clicked() ? 'orange' : 'red' });

return <button onClick={() => setClicked(c => !c)} style={style()}>
{props.children}
</button>
lxsmnsyc
lxsmnsyc12mo ago
That creates a new proxy every update, which is an anti-pattern. It is practically the same as just {...props.style, color: myValue() } I'd recommend just turning color into a getter
Liquido
LiquidoOP12mo ago
Can you please elaborate why that's the case? When a signal is updated, how is getter different than just updating the styles? Does Solid signals automatically update nested fields, which is more efficient?
lxsmnsyc
lxsmnsyc12mo ago
with just the getter, you're only calling mergeProps once thus not creating a new object every reaction. In your case, you're creating it every reaction.
Want results from more Discord servers?
Add your server