S
SolidJS4mo ago
gabriel

Setting properties to the unwrapped value of a store doesn't always propagate into the store

This is a bit of a mouthful but its actually a simple thing to see if you consider the following playground: https://playground.solidjs.com/anonymous/671217f5-1742-45be-932f-494c85ee3a85 I also opened an issue on this because I feel a lot like this is a bug https://github.com/solidjs/solid/issues/2085. I wonder if someone also had a similar use case or issue like this, would love to talk about it a bit here.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
GitHub
Issues · solidjs/solid
A declarative, efficient, and flexible JavaScript library for building user interfaces. - Issues · solidjs/solid
23 Replies
gabriel
gabriel4mo ago
Note: one of the cases in which this does work is if you just don't set the value in the store at all, and then you keep comparing both, it's always the same. feelling like this might be the culprit here https://github.com/solidjs/solid/blob/8de75a47bc535379ae9ae1cc77797d35a1e10868/packages/solid/store/src/store.ts#L209-L238
bigmistqke
bigmistqke4mo ago
What is the usecase here? It's a very unusual way of managing a store.
gabriel
gabriel4mo ago
@bigmistqke I'm doing kind of a component system for the data, and I need to sync the instances with the original component sorta like figma I thought it would be easier to first make an object that supports this, that would be independent of createStore, to then use it in the store because Solid directly makes changes to the underlying object, but now I'm unsure just don't want to do it through effects
bigmistqke
bigmistqke4mo ago
Have u looked at reconcile?
gabriel
gabriel4mo ago
I haven't looked into it a lot, just used it a few times, how would a pseudo-solution look like if I used it? like with a fake
const [component, setComponent] = createStore({});

const [instance, setInstance] = createStore({});
const [component, setComponent] = createStore({});

const [instance, setInstance] = createStore({});
I would consider using an effect as long as it ends up being maintainable the issue is that my original code for this here is just stupid to understand and maintain
bigmistqke
bigmistqke4mo ago
Mm ye I think I m missing a bit the overall picture tbh. If u could make a minimal reproduction of what ur trying to accomplish I can think along
gabriel
gabriel4mo ago
I'll give it a try
gabriel
gabriel4mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
gabriel
gabriel4mo ago
lmk if this is enough Still from the solution I was trying to get originally, I found that something like the follwing does actually work:
const [signal, setSignal] = createSignal("fake value");

const [store, setStore] = createStore({ name: "John" });
setStore('name', 'John man');
setStore(reconcile({
get name() {
return signal();
}
}, { merge: true }));
// setSignal('fake value 2');
expect(store.name).toBe('fake value');
const [signal, setSignal] = createSignal("fake value");

const [store, setStore] = createStore({ name: "John" });
setStore('name', 'John man');
setStore(reconcile({
get name() {
return signal();
}
}, { merge: true }));
// setSignal('fake value 2');
expect(store.name).toBe('fake value');
Only issue is that if you uncomment the setSignal there and update the final expect it doesn't anymore I guess Solid doesn't move the getter into the store, just accesses it and sets the value through it
bigmistqke
bigmistqke4mo ago
I see, so u want to do some sort of inheritance type stuff? Where any property that isn't set by setInstance is in sync by the component-store? Ye combining setters and store seems to be kinda bugprone I think u can manage the base idea with splitProps and composing stores Something like
const instanceStoreData = splitProps(componentStore, ['propName'])
const [instance, setInstance] = createStore(instanceStoreData)
const [propName] = createStore({propName: ...}})
setInstance({propName})
const instanceStoreData = splitProps(componentStore, ['propName'])
const [instance, setInstance] = createStore(instanceStoreData)
const [propName] = createStore({propName: ...}})
setInstance({propName})
I m on my phone rn so can't rly properly test it.
gabriel
gabriel4mo ago
I see, so u want to do some sort of inheritance type stuff? Where any property that isn't set by setInstance is in sync by the component-store?
Yup, exactly that so, in that case I would have to know what properties were set in the instance to then split it in that way? Also, I think Solid would propagate the sets for the setInstance up into the componentStore with that
bigmistqke
bigmistqke4mo ago
1. Yes, but you can get that information from setInstance. 1 layer it's probably not going to be too difficult (store.property) but supporting deeper layers might be a bit tricky (store.property.property) 2. No, that's what the splitProps is for
gabriel
gabriel4mo ago
No, that's what the splitProps is for
Hmmm, didn't know it also avoided that kinda thing
Yes, but you can get that information from setInstance. 1 layer it's probably not going to be too difficult (store.property) but supporting deeper layers might be a bit tricky (store.property.property)
Yeah, that's what I'm thinking, does splitProps allow for splitting deeply as well?
bigmistqke
bigmistqke4mo ago
A wait had a typo Should have been
const [,instanceStoreData] = splitProps(componentStore, ['propName'])
const [,instanceStoreData] = splitProps(componentStore, ['propName'])
Yeah, that's what I'm thinking, does splitProps allow for splitting deeply as well?
You could do
const [, store] = splitProps(store.property, [...])
const [, store] = splitProps(store.property, [...])
That's what I m thinking at least But ye, kind of a Hard Problem. Store's API is also pretty complex, to support all of the features will be pretty tricky I think.
gabriel
gabriel4mo ago
Getting to thinking that I could define a different primtive for this, probably the best I'll tell you what I can come up with
bigmistqke
bigmistqke4mo ago
My original idea doesn't work. splitProps does give a reference to the store without the property, but once you merge it with a new one it will just revert to the original component-store. Probably a side effect from store being a proxy under the hood.
bigmistqke
bigmistqke4mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
gabriel
gabriel4mo ago
but once you merge it with a new one it will just revert to the original component-store.
Do you mean that the set from the instance propagates into the component one?
bigmistqke
bigmistqke4mo ago
https://playground.solidjs.com/anonymous/2293303f-a93a-480c-85d3-85249b8ba404 is playground with a bunch of experiments. instance is the initial idea I had with splitProps and mergeProps
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke4mo ago
but as this example showcases, it is theoretically possible. you will just have to write a custom merge-function
bigmistqke
bigmistqke4mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke4mo ago
🙏 chatgpt
gabriel
gabriel4mo ago
honestly I'm kind of afraid of what kind of bugs I can get with createMutable I generally find they're pretty good for what I want, just my use case is kind of taking solid's state mechanisms to the extreme
like noticing the unwrapped value changes with the store, thats recipe for problems in the future
Yeah probably, I think the primitive approach based on createStore and splitProps is going to much more stable