<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
I did not even know Show had a callback...
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
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 workaroundBecause 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 changesright, 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
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
This would not be reactivesince the callback is just a
children
prop that Show
takes, it can decide whatever it likes.
like here
if you pass keyed
to Show
the callback will receive the value passed to when
prop as is and re-run the callbackI 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
I was only mentioning it to add to the first point
ah gotcha
to be clear I do understand why
Show
isn't tracking signalsthe fact that you are passing
_ => count()
proves that point
because that's on Show
to decideWhen 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
maybe an example of what you're trying to do would help picture this. as the original playground was just counters.
it's the same issue here, the the signal isn't accessed in a reactive scope
the show callback is not reactive
JSX is