Template doesn't react to property change in store of array of objects
Using either of the 2 methods, when I log the users store, I see that the name of the user has changed in the store object. However, the template doesn't update/react to the new name. Why is that?
26 Replies
The problem is that the reference for currUser may not match.
if you used
setUsers(0, "name", userName())
, it would work AFAICT.However, I can see the change in the store object itself
That is because currUser does not need to be reference-identical to the previous object to show the change.
Objects in stores are not ref-safe.
But I am not replacing any objects? I am sorry but I'm not sure I fully understand what you're trying to say. Using both store update methods, inspecting the store object reveals that the name key on the user object indeed updated as expected. However the template does not reflect the change.
The problem is that the users[0] you read at the start is the result of a proxy operation.
What does ref-safe mean? Just so we speak the same language 🙂 Thanks
Objects are stored by their reference on the stack.
{} == {} // false
here you can see that two empty objects have different references.
But this function
(user) => user === currUser
, which is used in both methods, does match the object by reference.That's the issue.
user is the user from the underlying object, currUser is from the proxy.
I appreciate your help but it's too terse for me to fully grasp your point. Is the fact that they are matching a problem?
A Proxy is able to wrap objects and interject the access on the object. It inherently has a different reference than the underlying object. The problem is that you attempt to compare the reference of a proxy object with the underlying object, which will never match, so the amount of users selected is neccessarily empty.
Solid's stores are based on Proxies to intercept reading and allow to track the access inside effects and memos.
If you want to have unique user names, maybe try a
ReactiveSet<string>
instead: https://primitives.solidjs.community/package/set#reactivesetSolid Primitives
A library of high-quality primitives that extend SolidJS reactivity
@Alex Lohr Thanks, but the actual object is a bigger class. My code example is just a simplification of the pattern. However the essentials are identical 🙂
Below is a screen shot of a debugger on the code. As you can see, the 2 objects are matching in the find callback (you can see
Return value: true
on the right).
And as I explained, when inspecting the store, I do see the updated user nameIf they're classes, they aren't reactive by default because Solid doesn't automatically wrap class properties to make them reactive
@REEEEE you mean each user, right? Yes, each user is a class. How could I get around this limitation?
well if there's only some properties of the class that need to be reactive, you can make them signals. If you want to make all properties of a class reactive, you can do
Thanks. That's creative. Possible to wrap a signal with a getter and setter right?
you would have to do something like this
If you use
createMutable
, it will work automaticallyI see. That's cool. However this class also has some more complex objects and arrays as props. Is it possible to explicitly exclude them from
createMutable
? Or is it all-inclusiveAt the moment it's all inclusive, you can take a look at this conversation and implementation instead
https://discord.com/channels/722131463138705510/990790895244808192/1285379168602951793
@REEEEE Thank you very much, that's an interesting link. Just been experimenting with
createMutable
, what would be the correct way to locate the current user for updating - assuming there's no id or index? Now they are in fact not matching anymore, as @Alex Lohr expected.
Assuming
user
and currUser
and both the same underlying class instance, they should match I would imagine but I suppose the introduction of the proxy would break it. You would probably need a unique identifier for them in that case
This is partly where createMutable
breaks rather than creating individual signals per propertyGot it. Since at the moment the class has only 2 properties that warrant reactivity I'm opting for the direct getter/setter method. But I'll definitely keep this lesson in mind. Thanks!
There is a way, you can access the underlying object using
unwrap
: https://docs.solidjs.com/reference/store-utilities/unwrap@Alex Lohr that's right, I'm even using it somewhere else. Thanks!