S
SolidJS2y ago
Max

function prop destructure

Just wondering if there are any implications of passing only accessors or functions as props and then destructuring them vs passing values directly and accessing from props object. I know the reactivity linting is limited in what it can detect but besides that are there some things that should be thought about. More generally are there any good resources to really understand the reactivity system in solid, I've seen some of the older discussion and issues on solid's github has interesting stuff to read but looking for a somewhat structured explanation that goes into some detail.
13 Replies
thetarnav
thetarnav2y ago
it's only about DX reactivity will work either way
Max
MaxOP2y ago
nice thanks
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
mdynnl
mdynnl2y ago
destructuring props is fine if you pass accessors or functions as opposed to passing values by calling, that's what the OP is asking as for reactivity learning resources, take a look at ryansolid's dev.to or medium like this one https://itnext.io/designing-solidjs-reactivity-75180a4c74b4 https://dev.to/ryansolid/a-hands-on-introduction-to-fine-grained-reactivity-3ndf
Andreas Roth
Andreas Roth2y ago
No it's not... What if someone uses the component in a way that changes the accessor?
function Inner(props: { n: () => number }) {
// Only takes the first version of the accessor
const n = props.n;

return <button>{n()}</button>;
}

function GoodOuter() {
const [n, setN] = createSignal(0);

// Works because it is always the same accessor
return <Inner n={n} />;
}

function BadOuter() {
const [a, setA] = createSignal(0);
const [b, setB] = createSignal(100);

const [useA, setUseA] = createSignal(true);

return (
<div>
<button onClick={() => setUseA(!useA())}>Toggle</button>
<Inner n={useA() ? a : b} />
</div>
)
}
function Inner(props: { n: () => number }) {
// Only takes the first version of the accessor
const n = props.n;

return <button>{n()}</button>;
}

function GoodOuter() {
const [n, setN] = createSignal(0);

// Works because it is always the same accessor
return <Inner n={n} />;
}

function BadOuter() {
const [a, setA] = createSignal(0);
const [b, setB] = createSignal(100);

const [useA, setUseA] = createSignal(true);

return (
<div>
<button onClick={() => setUseA(!useA())}>Toggle</button>
<Inner n={useA() ? a : b} />
</div>
)
}
We should never break reactivity just because it works in some cases... If you can break the component by "using it wrong", the component implementation is broken
mdynnl
mdynnl2y ago
passing only accessors or functions as props and then destructuring them
it's only about DX reactivity will work either way
destructuring props is fine if you pass accessors or functions as opposed to passing values by calling, that's what the OP is asking
i agree if you're talking about like writing component libraries or something that gets used by others, but if you're just using it for your own app, it's fine at this point, one probably knows what one's doing
JCM
JCM2y ago
If expecting values as props, then the user of the component can pass a reactive value or a constant. It's more consistent for the user of the component. I guess the choice that solidjs made to wrap reactive values as getter function in the pros object comes from that. Personally I find this to be the better trade-of, and it doesn't bother me much to not destructure. I guess the biggest downside of expecting an accessor function in the props and destructure is the example shown above by @andreasroth .
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
mdynnl
mdynnl2y ago
i'm not comparing one approach to another nor arguing which one is superior (both approaches have its own pros/cons depending on your preferences) my point is just repeating myself if you know what you're doing, in this case, passing accessors or functions which will be used in every possible way, including destructuring props or whatever, is totally fine and works (of course if you can handle the complexity or simplicity depeding on how you see it), in fact, that is how solid works universally, jsx w/ or wo/ babel transform or just javascript to be clear, accessors or functions wrt reactivity aren't the complexities added, they were there to begin with, which solid's jsx transform hid it for simpler mental model and better dx
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
mdynnl
mdynnl2y ago
in the first example, Inner takes accessor n as prop, which is going to be destructured, hence, you'll always have to pass an accessor to it deferring the evaluation of anything dynamic () => dynamic() ? foo() : bar() not doing so useA() ? a : b is similar to breaking reactivity by destructuring props in the passing values paradigm (backed by jsx transform)
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
mdynnl
mdynnl2y ago
almost everywhere, except jsx on, createMemo, createEffect, ... and you'll use that same understanding to implement secondary utilities (or primitives as some like to call) and destructuring is not a hard rule, i'm really sad that the narrative destructuring (props?) breaks reactivity didn't change that much imo, it's better to show the most basic working thing then reveal improved form, then explain the benefits, feels like we're doing the reverse (i'm sure this has been said a few times in the past by some others that also got ignored) (hoping this will change in the future)
Want results from more Discord servers?
Add your server