Reactivity issues

Hi. I am coming back to Solid after a long hiatus for a brand new project. I have been stuck trying to solve a very annoying reactivity issue that I have. I have an object in a signal (I do not use a store because I want it to be undefined), value of which gets passed to a component via a prop. There are also props for modifying that object. This object has an array of other objects, and I am using Index to render it. Whenever I remove an object from that array, its data gets "shifted" around, until I modify an attribute of that array that has an effect on rendering. Using For fixes this issue but it introduces a plethora of other bugs, like the settings popover for that object losing focus from the text input element (because the element based on that object data is being remade, including the settings popover). I asked LLM AIs to no avail. In Vue, I'd usually fix that by assigning it a different key value to trigger a rerender. I am lost and confused, please point me to the right direction.
34 Replies
Madaxen86
Madaxen863mo ago
Maybe you can share a simple reproduction on https://playground.solidjs.com
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
polyzium
polyziumOP3mo ago
Let me see if I can I can't seem to easily reproduce the issue due to the complex amount of CSS I have, and the Solid playground doesn't seem to support dedicated CSS files.
polyzium
polyziumOP3mo ago
@Madaxen86 Here is my best attempt at a reproduction. While it doesn't reproduce the exact same scenario I have in my project, it has other side effects. To reproduce the issue exactly I'd have to introduce A TON of CSS into the mix which is in this case quite overkill. https://playground.solidjs.com/anonymous/1195067c-4cf0-4192-99f0-3e32058d3c01 I do not think I can do any better, I have a headache and I am tired.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
polyzium
polyziumOP3mo ago
If I replace the Index with For then nothing works at all. Oh my god.
fabiospampinato
fabiospampinato3mo ago
GitHub
solid-primitives/packages/keyed at main · solidjs-community/solid-...
A library of high-quality primitives that extend SolidJS reactivity. - solidjs-community/solid-primitives
polyzium
polyziumOP3mo ago
This one seems to re-render EVERYTHING regardless if it was changed or not. Or maybe I'm using the key argument incorrectly probably the latter Okay yeah I was using the key argument incorrectly Okay, yeah, looks like this is going to work! Thanks!
thetarnav
thetarnav3mo ago
I think the issue with using For is that you use only one signal, but mutate the array deeply For creates a value signal for each of the rendered items, if you mutate the item object that signal will not detect it as a change. you usually want to create signals for each value that you want to change. so you don’t mutate objects, but only assign signals
polyzium
polyziumOP3mo ago
So you're saying I need to create signals INSIDE the object itself?
thetarnav
thetarnav3mo ago
yeah thats what stores do
polyzium
polyziumOP3mo ago
This would likely conflict with the origin type that I'm assigning the data to, wouldn't it?
thetarnav
thetarnav3mo ago
and thats what you do when you don't use stores yeah you have Data and ReactiveData basically stores solve that by pretending they are the original type (just like refs and reactives do in vue btw) vue has shallowRefs which are signal equivalents
polyzium
polyziumOP3mo ago
In my case I want the object to be undefined, providing the editor a hint that there is no event data so it goes into date assign mode. Stores cannot be undefined and that's why I don't use them here, unless I want to check for an empty object, and checking for an empty object is... rough
thetarnav
thetarnav3mo ago
you can nest the data in an object {data: T | null}
polyzium
polyziumOP3mo ago
Hm good point I guess I was just trying to keep the codebase as concise as possible, so I am trying to avoid such bandaid solutions But would Solid track the said nested data deeply like it usually does? Is it smart enough to see that this is a union type that also can be nullish? Because I fear I might run into the same caveat here
thetarnav
thetarnav3mo ago
solid doesn't use types but there should be no issue
polyzium
polyziumOP3mo ago
I thought Solid uses TS under the hood? Or did I misinterpret your statement incorrectly?
thetarnav
thetarnav3mo ago
it's just runtime exactly like vue at least the reactivity
fabiospampinato
fabiospampinato3mo ago
maybe something like Key should be built-in btw 🤔 I've never needed it myself, but now I find myself writing a chrome extension that has to get what to render from another process, so necessarily references get broken, and I don't really want to throw a store at this (and my reconcile function doesn't even support matching up by "id" it seems)
polyzium
polyziumOP3mo ago
I agree, those coming from Vue will find this useful Actually now that I think about it TS just compiles to JS and doesn't even have any kinds of safeguards in runtime, so...
thetarnav
thetarnav3mo ago
I would still reconcile manually and use signals thats what I do in solid-devtools for everything
fabiospampinato
fabiospampinato3mo ago
doing it manually it very much non trivial I think, one has to sort of reimplement the mapping function
thetarnav
thetarnav3mo ago
generally if you use createMutable and Key you should have a very similar expirience as in vue
polyzium
polyziumOP3mo ago
Speaking of solid-devtools I wanted to check it out but I could not find a firefox extension for it
thetarnav
thetarnav3mo ago
there is a firefox version pretty sure it's just called solid-devtools or "Solid Devtools"
polyzium
polyziumOP3mo ago
I've never used createMutable, the store path syntax while disorienting at first is actually sufficient
thetarnav
thetarnav3mo ago
yeah just saying because in vue you usually just do data.value = some_json render it with for and key and it works solid forces you to be more explicit but the same is possible
fabiospampinato
fabiospampinato3mo ago
why torture yourself with setStore though
polyzium
polyziumOP3mo ago
I wouldn't call it torture Cloning the object, editing it and setting the signal to it - that's torture lol
fabiospampinato
fabiospampinato3mo ago
fair
polyzium
polyziumOP3mo ago
I just haven't yet explored how do Solid's mutable stores work under the hood as I never needed to use them
fabiospampinato
fabiospampinato3mo ago
basically for each property a signal is created/read/written under the hood for you
polyzium
polyziumOP3mo ago
But since my project focuses on UX I guess it could've made more sense to use I presume under the hood it is a proxy object with watchers of some kind? Never used proxies in regular JS let alone in Solid
fabiospampinato
fabiospampinato3mo ago
watchers? it is a proxy object that intercepts reads and writes, and a bunch of other things, but not everything necessary
polyzium
polyziumOP3mo ago
In Vue you could do watch(ref, () => {...}) to do something when the value of a ref changes, I believe an equivalent in Solid is createEffect(on(signal, () => {...})) That's why I called them watchers I've read up on proxies just now, looks like the image in my head was correct I suppose that's all from me for now, thanks all that was for sure enlightening

Did you find this page helpful?