Initializing y-codemirror.next provider for collaborative code editing in a React app

52 views Asked by At

I'm currently working on an online collaborative IDE using y-codemirror.next and uiw/react-codemirror to enable pair programming. I'm facing an issue with the initialization of the provider and passing the necessary props to my custom "Editor" component, where users can choose a room for collaboration.

The collaborative initialization script looks like this:

Collaborative init script

import * as Y               from "yjs";
import { WebrtcProvider }   from "y-webrtc"; 
import { USER_COLOR }       from "./constants";
import * as random          from "lib0/random";

const ydoc          = new Y.Doc();
export const ytext  = ydoc.getText("codemirror");


export const initCollaborative = (room, username) => {
    const provider  = new WebrtcProvider(room, ydoc, {
        signaling: [
            'ws://localhost:4444',
        ]
    });

    const undoManager   = new Y.UndoManager(ytext);
    const userColor     = USER_COLOR[random.uint32() % USER_COLOR.length];

    const awareness = provider.awareness;
    awareness.setLocalStateField(username, {
      name: "Anonymous " + Math.floor(Math.random() * 100),
      color: userColor.color,
      colorLight: userColor.light
    });

    return provider;
}

Component's source file

import { useEffect, useState, useRef } from 'react';
import CodeMirror  from '@uiw/react-codemirror';
import { python }  from '@codemirror/lang-python';
import { yCollab } from "y-codemirror.next";
import { initCollaborative, ytext } from './collaborative'; // file from before

export const Editor = (props)=>{
    const {room, username} = props;
    const [value, setValue] = useState( ytext.toString() || "");
    const [extensions, setExtensions] = useState([python()]);

    const onChange = (editor, viewUpdate) => {
        setValue(editor);
    }

    useEffect(()=>{
        const provider = initCollaborative(room, username);
        setExtensions([python(), yCollab(ytext, provider.awareness)]);
    }, [])

useEffect(()=>{
    setValue(ytext.toString())
}, [ytext])

return (
    <div id="editor">
        <CodeMirror
            value={value}
            onChange={onChange}
            extensions={extensions}
        />
    </div>
    )
}

My struggle is understanding where to place the initialization of the provider to pass the username and room props to my "Editor" component dynamically. Any insights or suggestions on how to structure this initialization for optimal performance and flexibility?

What is showed up is not working, as it is giving problem trying to create too much times the room (even if called inside the useEffect). I didn't manage to find any correct example with initialization inside the component, as is always used another script with static room name.

0

There are 0 answers