<Show> not tracking signals

For some reason when I use another signal inside of Show's callback, it does not track that signal. When I don't use Show's callback, everything works fine. https://playground.solidjs.com/anonymous/9581e103-9f05-4744-ba92-f285dc89d19f
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
14 Replies
Ximaz
Ximaz2mo ago
I did not even know Show had a callback...
Madaxen86
Madaxen862mo ago
I can’t really explain this. It may be that Show does not realise that the reference to the map has changed!? You can check solid primitive’s reactive map https://primitives.solidjs.community/package/map#reactivemap
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
webstrand
webstrandOP2mo ago
I don't think it's that, the Map reference doesn't change it's that Show doesn't seem to be capturing the use of signals in its callback this may be intentional, but it's weird and I'd like to know why {counter => <>{counter().amount}</>} works as a workaround
REEEEE
REEEEE2mo ago
Because it's being read inside jsx which tracks but in the original all you're doing is taking the passed callback and returning the value. The reference to counter() doesn't change unless the value in the when condition also changes
webstrand
webstrandOP2mo ago
right, because solid doesn't track signals called by the base component function. It feels weird though since visibly that callback is being called in jsx scope, so in most context signals inside it would be tracked
REEEEE
REEEEE2mo ago
You can think about it like it's another component you just created and your accessing the reactive property in the body rather than the returned jsx. The same thing would fail if you had a component that just returned props.value outside of the jsx
function Counter(props){
return props.count
}
function Counter(props){
return props.count
}
This would not be reactive
mdynnl
mdynnl2mo ago
since the callback is just a children prop that Show takes, it can decide whatever it likes. like here
<Show keyed ....>
{count => count.amount}
</Show>
<Show keyed ....>
{count => count.amount}
</Show>
if you pass keyed to Show the callback will receive the value passed to when prop as is and re-run the callback
webstrand
webstrandOP2mo ago
I think I've confused things by failing to create a more minimal reproduction, here's a better example: https://playground.solidjs.com/anonymous/6bf15907-ef7c-40dd-8e7e-4cfd941a477e the value passed through the <Show> is irrelevant, so I've replaced it with true
mdynnl
mdynnl2mo ago
I was only mentioning it to add to the first point
webstrand
webstrandOP2mo ago
ah gotcha to be clear I do understand why Show isn't tracking signals
mdynnl
mdynnl2mo ago
the fact that you are passing _ => count() proves that point because that's on Show to decide
devagr
devagr2mo ago
When you do <Show>{expression}</Show>, the expression is considered a reactive expression by the compiler. When you do <Show>{() => something}</Show>, this is not a reactive expression, just a callback to render the UI once. To track a signal, it has to run inside a reactive expression, which is why you need to wrap it in a fragment <>{counter().amount}</> so that the signal is read reactively it's like if you read a signal inside a component body and return its value instead of reading the value inside jsx
mdynnl
mdynnl2mo ago
maybe an example of what you're trying to do would help picture this. as the original playground was just counters.
devagr
devagr2mo ago
it's the same issue here, the the signal isn't accessed in a reactive scope the show callback is not reactive JSX is
Want results from more Discord servers?
Add your server