Confused about resource mutation with `createDeepSignal` and `produce`
Hey folks,
I am trying to create a resource which gets updated on a button click, by fetching content from a server.
However the user may change parts of the data they have already fetched. When refetching the data, we want to make sure that all user changes are not being overwritten.
To allow changing small parts of the data and still being reactive, I use
createDeepSignal
from solid-primitives.
My resource is initiated like this:
Store here is a persisted file.
By default this file is empty until the user fetches projects from a remote server for the first time.
This fetch function can be used repeatedly and should alter its behaviour depending on if the user already has fetched projects or not as described above.
My fetch function looks like this: (continuation in comment)11 Replies
However this does not work unless I remove the call to
produce
inside the call to mutate.
I don't quite understand why that is. I also have other actions where I toggle a property of a single project (without fetching anything) where I strictly need produce to achieve reactivity. For example:
Can anyone explain to me, why these two are different and what I am missing here?
Thanks in advancemy two cents: produce works like in
immer
. the state
you receive in the callback is going to be a proxy that registers all the mutations of that object in the callback, and then set its inner state according to those mutations. state = syncedProjectsState
will not work for that reason, because with a proxy you can only listen to changes on a property of the proxy (one of proxy's biggest gotchas). state = syncedProjectsState
will work with simple mutation, since you are directly setting the reference.Ah yeah that might be the issue at play here. Hm, I'll have a deeper look at this. A few hours ago I tried to create a minimal example and play around with it, but the result wasn't reactive at all. I assume I must have messed up there as well.
Anyway, thanks for your answer 🙂
hm, while what you wrote is obviously true, I still can't get a working example at all. I think the missing part is overwriting the
deepSignal
at the top level. What would be the correct way to override the complete state here? (in other words, how can I not just update a property of my resource, but the whole resource itself?
Simplified example:
oh, wait, this mutate((_) => ({ a: 'overwrite', b: 'overwrite' })
seems to work, which is exactly what @bigmistqke was writing, right? I must've messed up somewhere before...createDeepSignal
is pretty much this:so as you can see it's already using
reconcile
, which cannot be just combines with produce
hm, so I shouldn't use produce at all with deepSignals?
to have a normal store settter for
mutate
and still reconcile
on refetch you have to wire the setter a bit differentlyhm, man this is pretty hard to wrap my head around. I just started solid coming from years of react 😄
like the problem are:
1. types -
mutate
will alwyas have a Setter
type, so it needs to be typecaseted to StoreSetter
I think
2. how do you determine if the setter was called with mutate
or by refetching?
stores add a layer of abstraction so it's hard to be able to handle custom cases if you don't know the basicsyeah. So maybe my approach isn't the best in general. I'll try to rephrase, what I want to achieve:
- I have a list of projects
- initally, when the app is started for the first time, the user does not yet have that list
- instead they have to fetch it from a server
- this list of projects is then persisted to a file
- the next time the user starts the app, the list will be fetched from said file (this is the actual resource)
- however this list might update on the server so the user can push a button to refetch the list
- the user can also adjust settings on items of this list, so when they refetch we want to avoid to override these custom changes
The more I think about it, this architecture might be bad anyway. I might make sense to normalize this a bit more and save these settings separate from the list of projects. We would then not have to worry about the case of overriding local project settings and could focus on the case of overriding the whole store.
Thanks btw., really appreciate you folks taking the time to help out! ♥️
This seems to work, right now (but I am questioning this architecture in general):
something like this might help
not sure if it works exackly and probably could be improved
like you could create the store first, pass the reconciling store setter to the resource, and use normal setter in your app