Registering Observers

Hi!

Thanks for this amazing library. I’ve been watching this project for a while but just am trying to use it again after a while. Obviously I’m missing something… any help would be much appreciated!

I’m working on a collaborative canvas app, but I’m having trouble registering observers using the follow pattern:

  const yDoc = new Y.Doc();

  const root = yDoc.getMap("root");
  root.set("version", "0");
  root.set("name", "Untitled");
  root.set("slug", "slug");
  
  const sceneNodesArray = new Y.Array<SceneNodesAll>();
  const sceneNodes = root.set("sceneNodes", sceneNodesArray);

  sceneNodes.observe((event, transaction) => {
    console.log(
      event,
      transaction
    );
  });

When I’m updating the array I do:

const root =  this.yDoc.getMap<LiveLayoutStorage>("root");
const sceneNodes = root.get("sceneNodes");

sceneNodes.push([
  new Y.Map(...)
]);

It seems to work if I create the Y.Array directly on the Y.Doc. Does the observer need to be declared directly on a top level shared type?

const sceneNodes = yDoc.getArray<SceneNodesAll>("sceneNodes");

sceneNodes.observe((event, transaction) => {
    console.log(
      event,
      transaction
    );
  });

Thanks in advance! :pray:

Both top-level shared types and shared types created with new support .observe.

In your first example you retrieve a top-level YMap with the name "meta", and in the second example you retrieve a different top-level YMap with the name "root".

Is that intentional?

Hi @raine thanks for your reply!

No that wasn’t intentional - both should use the key "root"… I was trying a few different things and copy-pasting while I typed this question. I’ve edited it to better reflect what I’ve been trying.

It seems to work for me:

But perhaps I’m not understanding what exactly is not working for you.

1 Like

Ok thanks so much for that minimal example. That’s exactly what I’m trying to do and I see that it’s working in your example.

I think my issue is passing around potentially stale references to yDoc… it seems that if I save a reference to it in an object and then try to modify it, the observer isn’t called.

I’m working in an existing project that’s kind of complex in which I want to observe state both in React and in some javascript classes. Do you have any advice there? I’m starting to get things working by operating on the original reference to the Y.Doc, but it still seems a little … unpredictable? I probably just need to keep tinkering…

A couple gotchas that may or may not be related:

  • Always subscribe to the observe handler before changes are made to the shared type (local updates to shared types are synchronous).
  • Careful when initializing nested shared types. ymap.set will overwrite anything that is there already. Either wait for your providers to sync, or use top-level types.

I think with some tinkering you’ll find the cause of the problem and it will feel reliable again. Concurrency is a %F$#… :slight_smile:

1 Like

Hey @raine - thanks again for taking the time to help me.

Soo… I figured out my issue - I was basically creating two instances of Y.Doc accidentally. I was so focused on learning Yjs I forgot about everything else.

Thanks for the sanity check and the extra tips!

Glad you figured it out! I totally understand. It’s always the things we take for granted that hide the most elusive bugs :).