Root Registry / Backrefs with deep observation
PEZO19 opened this issue · comments
Rationale:
It would be really nice to get updated about all changes (also deep updates) of all instances of a given Model in a canonical way "at a central place".
As I understand from keystone docs and the implementation, getRefsResolvingTo
gives you back a standard mobx ObservableSet
, which does not seem to support deep observation (by default). It would be nice to get updated about the deep changes of this ObservableSet
. Is it a preferred/canonical way to do it in keystone? Is it preferred to use it with mobx-utils' deepObserve? I myself did not try it out yet, but have found this Open issue: deepObserve not working with ObservableSet. I also mind updateAllRefsIfNeeded=true
case.
Am I missing something?
you can use a plain mobx reaction with getSnapshot to do it (since snapshots create a new ref any time anything inside that snapshot mutates)
reaction(() => getRefsResolvingTo(x).map(ref => getSnapshot(ref.current)), () => {
// this would trigger every time the set or any model in the set deeply mutates
});
@xaviergonz I see, however this does not provide me the changes (and path) inside this (deeply) observed observable, right? How could I get "path" and "changes" like this below?
deepObserve(target, (change, path) => {
console.dir(change)
})
Sorry, maybe nested onPatches
is totally fine for my use case (without deep observation), let me get back here later. Wondering if there is a pattern/antipattern related to this.
Just for the record, I want to do something very similar proposed by @xaviergonz here: #436 (comment)
However my current issue is that I can't really setup nested onPatches
, because in case of an outer add
Patch, I can't setup the inner onPatches
, because objectToAdd
is not part of the tree yet. See below.
onPatches(collection, (collectionPatches, collectionInversePatches) => {
collectionPatches.forEach((collectionPatch) => {
if(/*it is an "add" Patch I'm interested in*/) {
// I'd like to setup a "deep observation"
const objectToAdd = ... // we can get it from collectionPatch (eg. via path)
onPatches(objectToAdd, ...)
// ^ gives this error:
// subtreeRoot must be a tree node (usually a model or a shallow / deep child part of a model 'data' object)
}
// ...
})})
I assume, instead nested onPatches
I have to use nested "raw" mobx observe
calls for that, right?
Is there any important downside of doing that / any gotchas you are aware of (in context of using keystone that way) ?
Root registry with observation:
My current approach is maintaining a single ObjectMap
registry per keystone Model
and using mobx observe
on ThingObjectMapRegistry.items.$
(instead relying on onPatches
which was mentioned by me above, because onPatches
fires at the end of the transaction and is too late for me).
Root registry with deep observation:
(multiple Registries, items referencing to each other eg.: "pet" in "PetRegistry" has a reference on "Owner" which lives in "OwnerRegistry")
Using the basic idea of mobx-utils deepObserve
, I am setting up these "deepObserve(AtPath)" chains by hand using the .$
observable
part as mentioned above.
About refs/backrefs:
If refs are going to be needed, I think I'll use a customRef
which uses that thingObjectMapRegistry
.
For backrefs, I have realized, that I can not/ do not want to use getRefsResolvingTo
, for complex cases it is not powerful enough and explicit modeling of references is needed. (Eg. if I am interested "how/where" the ref source uses the ref.)
These might not really be the scope of keystone and the use cases are really custom and complex so I close the issue, but if anyone has comment on these, I'd appreciate it.