S
SolidJS3mo ago
Max

Possible to define more specific predicated for when prop on Match or Show

Hi, this is kind of a follow up to a previous question I posted that was about Show at https://discord.com/channels/722131463138705510/1280469354387079250, but I thought I would take some time to make more clear what I might be looking for. Basically it seams to me that the api in charge of resolving the outcome of show or switch based on when prop is always using truthy and falsy implicitly so its not possible to specify certain conditions to use for when prop. I think a simple example can explain better. Let's say I had some value and it could be a string or number or boolean.. And I want to render it in a component by looking at its type. I have this kind of utility function to look at the type of a variable and return the variable as that type if it is that type and return undefined if it is not. This is just for boolean for simplicity, I also don't think this function matters much for this issue but it gives some context to what i was trying.
18 Replies
Max
MaxOP3mo ago
const asMaybeBoolean = (value: unknown): boolean | undefined =>
typeof value === "boolean" ? value : undefined;
const asMaybeBoolean = (value: unknown): boolean | undefined =>
typeof value === "boolean" ? value : undefined;
So if I have two variables and one is true and one false, if I use the following logic to try and render the booleans I'm not able to get the false value to render because its falsy. If I have a simple test like this
function Test() {

const booleanTrue: boolean = true;
const booleanFalse: boolean = false;

const someValueA: unknown = booleanTrue;
const someValueB: unknown = booleanFalse;

const asMaybeBoolean = (value: unknown): boolean | undefined =>
typeof value === "boolean" ? value : undefined;

return (
<>
<pre style={{"font-style":"italic"}}> renders if boolean value is true</pre>
<Switch fallback={"no value"}>
<Match when={asMaybeBoolean(someValueA)}>
{(v) => <pre>bool: {JSON.stringify(v())}</pre>}
</Match>
</Switch>

<pre style={{"font-style":"italic"}}> does not render if boolean value is false</pre>
<Switch fallback={"no value (fallback)"}>
<Match when={asMaybeBoolean(someValueB)}>
{(v) => <pre>bool: {JSON.stringify(v())}</pre>}
</Match>
</Switch>
</>
);
}
function Test() {

const booleanTrue: boolean = true;
const booleanFalse: boolean = false;

const someValueA: unknown = booleanTrue;
const someValueB: unknown = booleanFalse;

const asMaybeBoolean = (value: unknown): boolean | undefined =>
typeof value === "boolean" ? value : undefined;

return (
<>
<pre style={{"font-style":"italic"}}> renders if boolean value is true</pre>
<Switch fallback={"no value"}>
<Match when={asMaybeBoolean(someValueA)}>
{(v) => <pre>bool: {JSON.stringify(v())}</pre>}
</Match>
</Switch>

<pre style={{"font-style":"italic"}}> does not render if boolean value is false</pre>
<Switch fallback={"no value (fallback)"}>
<Match when={asMaybeBoolean(someValueB)}>
{(v) => <pre>bool: {JSON.stringify(v())}</pre>}
</Match>
</Switch>
</>
);
}
that can be found here https://playground.solidjs.com/anonymous/a11336ad-e2b3-44f5-a334-0c3d571644f3. Then you can see false does not render. If I change the when prop to something like
<Match when={asMaybeBoolean(someValueB)!==undefined}>
<Match when={asMaybeBoolean(someValueB)!==undefined}>
then it is true so works but the argument I get for the value in callback is true because its the return from predicate, rather than being the actual value of the variable. So far I've been able to work around this by using the non callback form of Show / Switch or also by boxing the values in an object or array
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Max
MaxOP3mo ago
I'm wondering if I'm missing something or using something incorrectly, I feel like this would be a fairly common case, so there must be some clean way of doing this. So that for booleans false can be returned as argument to callback functions and for numbers 0. Thanks for any input if you got!
jer3m01
jer3m013mo ago
You can use anything as your condition, and you're not required to use the callback (but you lose typeguard) So you can have
<Match when={typeof varname() === "number"}>
Number is {varname()} // however typescript doesn't understand type as number and thinks it might be undefined/null
</Match>
<Match when={typeof varname() === "number"}>
Number is {varname()} // however typescript doesn't understand type as number and thinks it might be undefined/null
</Match>
Max
MaxOP3mo ago
thank you, yes what I'm doing now is using without callback which works because the when prop value is independent from the value, but I would like to have the convenience of the callback for control flow and additionally types. with ternaries it can work fine but I remember I think reading that Show and Switch etc.. are there for several reasons including that ternaries may not work optimially within the reactive scope
jer3m01
jer3m013mo ago
Yeah then a helper function like the one you made is needed they should be avoided (but work, at least currently)
Max
MaxOP3mo ago
okay nice thanks
jer3m01
jer3m013mo ago
You're probably able to make a generic helper function, something like maybeType(varname(), "number") => number | undefined
Max
MaxOP3mo ago
yea but I think it still wont work, that helper function is basically to get a convenient way to get types smoothly and normalize the type checking, but since the value is still false or 0 when it's evaluated it goes to switch fallback. So the issue is as far as i can tell nothing to do with typescript, even in js would cause issues
jer3m01
jer3m013mo ago
oh so you need it to work with falsy values?
Max
MaxOP3mo ago
yea that's my whole issue
jer3m01
jer3m013mo ago
you return a getter instead
Max
MaxOP3mo ago
I've used similar functions before but think it was just for object types so worked yes think that's what will have to do I have similar with boxed values in array etc, but it can be a bit awkard since the callback already returns an accessor, so would be accessor of accessor if pass the value as accessor but maybe its the smoothest way, like an object {value: <value>}
jer3m01
jer3m013mo ago
or a proxy maybe? not sure if they're falsy
Max
MaxOP3mo ago
yea that's a cool idea I'll have a look thanks for all the input helpful brothaa
Max
MaxOP3mo ago
also idk if you know, or anyone else? how keyed works. Would it only be for primitives? Only time I've seen something with keys in solid was using https://primitives.solidjs.community/package/keyed where you pass name of field to use as key, but would keyed on Show and Switch use the value itself as key?
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
jer3m01
jer3m013mo ago
keyed makes the component rerun when the value changes
Max
MaxOP3mo ago
ah okay thanks, so it makes the entire callback fn rerun? instead of just relying on the nature of signals for granular updates?
jer3m01
jer3m013mo ago
yes
Want results from more Discord servers?
Add your server