Hi there-
I have a “working” solution for a live notes page using React, Quilljs, Yjs, y-websocket and y-quill.
Though the document is connecting and does seem to receive updates successfully, I am constantly receiving disconnect errors and sometimes the document does not connect at all.
Below is my current solution- is there anything within that may be an indicator of what is wrong?
import React, { useState } from "react";
import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";
import { QuillBinding } from "y-quill";
function LiveNotes(props: any) {
React.useEffect(() => {
if (!connProvider) return;
connProvider.on("connection-error", (event: any) => {
connProvider.disconnect();
messageApi.error("Error connecting to note.");
quill.setText("Error connecting to document.");
});
});
// Start Connection. I also create a Y.doc on the serverside (assuming that is best practice).
React.useEffect(() => {
if (quill == null || documentId == undefined) return;
if (!binding) {
const ydoc = new Y.Doc();
const fakeID = "";
const provider = new WebsocketProvider(
`${websocketURL}?Authorization=${CONTEXT.oktaToken}&Subscription-Key=${SUBSCRIPTION_KEY}&type=note¬e_id=${documentId}&user_token=${userToken}`,
fakeID,
ydoc
);
setConnProvider(provider);
setTempYDoc(ydoc);
// User is authenticated within initial connect. Document should also load from db.
if (provider.ws) {
setAuthenticated(true);
quill.enable();
}
}
}, [quill, documentId]);
// Periodically send updates to db:
const sendDataSave: any = React.useCallback(
debounce((contents: any, prov: any, doc: any) => {
prov?.ws?.send(
JSON.stringify({
type: "document_save",
document: contents,
bytesDoc: fromUint8Array(Y.encodeStateAsUpdate(doc)),
})
);
}, 1000),
[]
);
// Update server after all else is established
React.useEffect(() => {
if (
!authenticated ||
!tempYDoc ||
!connProvider ||
!quill ||
!historyLoaded
)
return;
tempYDoc.on("update", (update: any) => {
// @ts-ignore
if (origin !== this && origin !== null) {
sendDataSave(quill.getText(), connProvider, tempYDoc);
}
});
}, [tempYDoc, quill, authenticated, connProvider, historyLoaded]);
// Bind textbox and user
React.useEffect(() => {
if (authenticated && connProvider) {
const ytext = tempYDoc.getText("quill");
const binding = new QuillBinding(ytext, quill, connProvider.awareness);
// Set the username for awareness
connProvider.awareness.setLocalStateField("user", {
name: userProfile.email,
color: usercolors[Math.floor(Math.random() * usercolors.length)],
});
setBinding(binding);
setAwareness(connProvider.awareness);
}
}, [authenticated, connProvider]);
return (
....notes container
);
}
export default LiveNotes;