Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Root Registry / Backrefs with deep observation #517

Closed
PEZO19 opened this issue Jun 4, 2023 · 5 comments
Closed

Root Registry / Backrefs with deep observation #517

PEZO19 opened this issue Jun 4, 2023 · 5 comments
Labels
❔ question General question

Comments

@PEZO19
Copy link

PEZO19 commented Jun 4, 2023

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?

@xaviergonz
Copy link
Owner

xaviergonz commented Jun 4, 2023

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 xaviergonz added the ❔ question General question label Jun 4, 2023
@PEZO19
Copy link
Author

PEZO19 commented Jun 4, 2023

@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)
})

@PEZO19
Copy link
Author

PEZO19 commented Jun 5, 2023

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.

@PEZO19
Copy link
Author

PEZO19 commented Jun 6, 2023

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) ?

@PEZO19
Copy link
Author

PEZO19 commented Jun 20, 2023

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.

@PEZO19 PEZO19 closed this as completed Jun 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❔ question General question
Projects
None yet
Development

No branches or pull requests

2 participants