Setting initial y-websocket content saved as markdown in DB

We have an application using y-websockets where we’d like to provide a few templates for our users. These templates are saved in markdown - the defaultValue var - because that’s what our editor (built on Prosemirror) takes in, before parsing it into nodes and so on

I took the advice here and only render the Editor once the socket is synced

But the data being read from our database - even though it initially is being read in correctly, is being over-written by empty editor content (a string with value "/"). Below is the useMemo() function I use to initialize the sockets. Is the approach incorrect?

  useMemo(() => {
    const ydoc = new Y.Doc();

    const yText = ydoc.getText("default-value");
    if (yText.toString() === "" && defaultValue) {
      yText.insert(0, defaultValue)
    }
    console.log(yText.toString()); //Logs correct string for defaultValue

    yXmlFragment.current = ydoc.getXmlFragment("prosemirror");

    provider.current = new WebsocketProvider(
      "wss://my-y-websockets.herokuapp.com",
      `${docID}`,
      ydoc
    );

    if (provider.current.shouldConnect) {
      provider.current.connect();
    } else {
      provider.current.disconnect();
    }

    provider.current.on("synced", () => {
      // received the initial content from socket, so allow editor render
      setYjsLoaded(true);
    });

    return () => {
      provider.current?.disconnect();
    };
  }, [defaultValue, docID]);

I noticed in this thread the suggestion to work with document updates rather than text updates. So I’ve also tried the following with the same result. I’m still seeing content get overwritten in the template with empty text

  useMemo(() => {
    const ydoc = new Y.Doc();

    defaultValue && ydoc.getText().insert(0, defaultValue);

    yXmlFragment.current = ydoc.getXmlFragment("prosemirror");

    provider.current = new WebsocketProvider(
      "wss://my-y-websockets.herokuapp.com",
      `${docID}`,
      ydoc
    );

    if (provider.current.shouldConnect) {
      provider.current.connect();
    } else {
      provider.current.disconnect();
    }

    provider.current.on("synced", () => {
      // received the initial content from socket, so allow editor render
      setYjsLoaded(true);
    });

    return () => {
      provider.current?.disconnect();
    };
  }, [defaultValue, docID]);

Try converting your prosemirror to a ydoc state using prosemirrorJSONToYDoc or prosemirrorToYDoc, then calling applyUpdate.

Thanks @bhl! Would that look something like the following, want to make sure I understand. Also what would need to be the data type of defaultValue? Would that be a serialized version of Prosemirror nodes?

      let ydoc;
      if (defaultValue) {
        ydoc = prosemirrorJSONToYDoc(schema, {
          type: "doc",
          content: [defaultValue]
        });
      } else {
        ydoc = new Y.Doc();
      }
    
      yXmlFragment.current = ydoc.getXmlFragment("prosemirror");
  
      provider.current = new WebsocketProvider(
        "wss://my-y-websockets.herokuapp.com",
        `${docID}`,
        ydoc
      );
  
      if (provider.current.shouldConnect) {
        provider.current.connect();
      } else {
        provider.current.disconnect();
      }
  
      provider.current.on("synced", () => {
        // received the initial content from socket, so allow editor render
        setYjsLoaded(true);
      });

That’s pretty close: the default value should just be something from EditorState.toJSON(). For example

let defaultValue = editorState.toJSON()
ydoc = prosemirrorJSONToYDoc(editorState.schema, defaultValue);

The data-type of defaultValue should be the json-serialized version of ProseMirror nodes yeah.