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

Cursors work great, but lose flags after a remount with React #70

Open
mattch opened this issue Sep 4, 2021 · 5 comments
Open

Cursors work great, but lose flags after a remount with React #70

mattch opened this issue Sep 4, 2021 · 5 comments

Comments

@mattch
Copy link

mattch commented Sep 4, 2021

I'm using Quill with React, Yjs, react-quill, y-quill, y-websocket, and quill-cursors. Everything works great with cursors (showing a remote users activity with a line without a flag) and with flags as long as there are no remounts. After a remount, the cursors continue to work but the flags stop showing up. This is because quillEditor.getModule('cursors').cursors() is empty. Before a remount, cursors() returns an array of users who are editing the doc, but after a remount, cursors() is always empty.

I've tried various combinations of saving (useRef) or recreating quill, cursors, binding, etc. For the most part, I fould the best approach is to store the WebsocketProvider, Y.Doc, Y.Text and then recreate the ReactQuill.getEditor, Quill.getModule('cursors'), and y-quill QuillBinding. I've tried different combinations, but all other combinations cause some other more serious problem (e.g. cursors stop working altogether).

I'm new to Quill, Yjs, etc., and I'm not really familiar with the relationship between all the packages, so not sure if this is a bug or something I'm doing wrong.

Any insights on what could be causing this or maybe just an explanation of how cursors() is populated?

thanks!

@alecgibson
Copy link
Collaborator

I can't say I'm particularly familiar with using Quill in combination with React. I'd have thought you wouldn't want Quill to be remounted ever? Have you got an example of other modules that work with a remount? A minimally-working example would also help a great deal.

@mattch
Copy link
Author

mattch commented Sep 6, 2021

Thanks for your help. Yes, I agree. I'm generally able to prevent Quill remounts most of the time, but with React it's always just a suggestion so remounts are still happening.

What's strange to me is that cursors still work after the remount and if I hover over the cursor, the correct flag is shown. The only real issue is that array from quillEditor.getModule('cursors').cursors() is always empty after a remount.

Can you explain how the array from cursors() is populated? There are so many packages involved. I'm not sure which one is causing the issue.

Here's a sample of the relevant parts. Sorry, I didn't create a codesandbox, but codesandbox was having issues with some of the libraries.

`
import React, { MutableRefObject, useCallback, useContext, useEffect, useRef, useState } from "react";
import ReactQuill, {Quill} from 'react-quill';
import * as Y from 'yjs';
import { QuillBinding } from 'y-quill';
import { WebsocketProvider } from 'y-websocket';
import QuillCursors from "quill-cursors";
import "quill-mention";

const EditorQuill = React.memo( (props => {
let provider: WebsocketProvider;
let binding:QuillBinding;
let editor:Quill;
let cursors:QuillCursors;
let quillRef: ReactQuill;

Quill.register('modules/cursors', QuillCursors);

// ref callback from 
const handleRefCallback = ( el =>{
        let {ws, ydoc, type} = YSocketManager.getSocket(room, user!.name, getCursorColor);  //Save socket between renders
        if (!ws ||  !ydoc ) {
            let ydoc = new Y.Doc();
            let type = ydoc.getText(room)
            let ws = new WebsocketProvider(YSocketManager.getInstance().host, room, ydoc);
        }

        editor = quillRef.getEditor();
        cursors = editor.getModule('cursors');
        binding = new QuillBinding(type, editor, ws.awareness);
    });

}

YSocketManager:
getSocket(room: string,userName: string, getCursorColor: ()=>string): {ws:WebsocketProvider, ydoc: Y.Doc, type:any}{
let roomMapEntry = this.roomMap.get(room);
if ( !roomMapEntry ) {
console.log("Creating new socket", room)
let ydoc = new Y.Doc();
let type = ydoc.getText(room)
let ws = new WebsocketProvider(this.host, room, ydoc);
ws.awareness.setLocalStateField('user', {
name: userName,
color: getCursorColor()
})

        ws.on('status', (event: string) => {
            //console.log("provider status", room, event)
        })
        this.roomMap.set(room, { ws, ydoc, type});
        roomMapEntry = {ws, ydoc, type};
    }
    return roomMapEntry!;

`

`return (
<ReactQuill
key={room}
ref={el => handleRefCallback(el)}
theme="bubble"
onChange={handleChange}
modules={{
cursors: {
hideDelayMs: 5000,
},
toolbar: toolbarOptions,
history: {
userOnly: true
},
mention: {
allowedChars: /^[A-Za-z0-9\sÅÄÖåäö]*$/,
mentionDenotationChars: ["@", "#"],
source: handleMention,
onSelect: handleSelect,
renderItem: handleRenderItem
}
}}
placeholder="collab-edit-test"

    />`

@mattch
Copy link
Author

mattch commented Sep 7, 2021

So I discovered that one of the packages I'm using is causing Quill to be unmounted and remounted. I'm looking to replace that package, but I'm still curious why cursors() is empty after a remount, yet everything else works fine. Any ideas?

@alecgibson
Copy link
Collaborator

Honestly, the package was never designed with a remount in mind, so its behaviour in that scenario is undefined and could do weird things like you're describing. If I were to guess, I'd have guessed that everything would stop working, not half of the package, but there we are.

Your best bet is to just force everything to stop remounting Quill (amongst other things, you'll lose the user's selection when that happens).

If you can put together a MWE that I can run, I can try to dig into the remount case to either try and fix it, or at least fail gracefully!

@mattch
Copy link
Author

mattch commented Sep 13, 2021

Yes, that's basically how I'm working around this. I basically don't allow the quill editor to rerender. I was seeing this issue on simple rerenders as well as remounts.

I'll work on the MWE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants