loadPaths() is laggy for data coming in from onUpdate() via socket-io (Collaborative canvas)
See original GitHub issueDescribe the bug Hello. Awesome work on the canvas!! I am trying to sync two whiteboards with each other. But the two keep getting laggy till it’s barely usable
To Reproduce When something is drawn on the first whiteboard, I get the CanvasPath[ ] from onUpdate() and send to the second whiteboard via socketio. On the second whiteboard, socketio captures the sent CanvasPath[ ] and I use loadPath() to display it on the screen. It works okay for the first few seconds and what is drawn on one end reflects quickly on the other. Then gets keeps getting laggy to the point where there is a huge delay. There is even a lag when drawing on the original whiteboard, leave alone reflecting on the other one. I also noticed that loadPaths() was trigerring onUpdate(), so I disabled socketio sending the paths until data is loaded
Expected behavior loadPaths() should not cause a lag
Screenshots If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: Kubuntu 20.04
- Browser : Chrome
- Version 86.0.4240.183
My code ` import React,{ useState, useEffect } from “react”; import { ReactSketchCanvas } from “react-sketch-canvas”; import ReactTooltip from ‘react-tooltip’; import { getsocketIoInstance } from ‘…/utils/socketio-client’;
export default class Whiteboard extends React.Component { constructor(props) { super(props); this.styles = { border: “0.0625rem solid #9c9c9c”, borderRadius: “0.25rem”, }; this.canvas = React.createRef(); this.state = { eraseMode: false } this.pauseSync = false; this.WhiteBoardMsgType = { canvas_draw: 1, canvas_undo: 2, canvas_redo: 3, canvas_clear: 4, } this.roomName = sessionStorage.getItem(‘roomName’); this.socketIo = getsocketIoInstance(this.roomName, ‘Whiteboard’); }
componentDidMount() { this.socketIo.on(‘whiteboard’, (changes) => { const { type, drawUpdates } = changes; if (type === this.WhiteBoardMsgType.canvas_draw) { this.pauseSync = true; this.canvas.current.loadPaths(drawUpdates); this.pauseSync = false; // setTimeout(() => { // this.pauseSync = false; // }, 50); } }); }
whiteBoardUpdated = (drawUpdates) => { if (!this.pauseSync) { const changes = { roomName: this.roomName, type: this.WhiteBoardMsgType.canvas_draw, drawUpdates } this.socketIo.emit(‘whiteboard’, changes); } // console.log(‘pause sync’, this.pauseSync); } toggleEraseMode = () => { this.canvas.current.eraseMode(!this.state.eraseMode); this.setState({ eraseMode: !this.state.eraseMode }) } undoCanvas = () => { this.canvas.current.undo(); // no need to send this change as they are already captured in the drawUpdates // const changes = { roomName: this.roomName, type: this.WhiteBoardMsgType.canvas_undo } // this.socketIo.emit(‘whiteboard’, changes); } redoCanvas = () => { this.canvas.current.redo(); // no need to send this change as they are already captured in the drawUpdates // const changes = { roomName: this.roomName, type: this.WhiteBoardMsgType.canvas_redo } // this.socketIo.emit(‘whiteboard’, changes); } clearCanvas = () => { this.canvas.current.clearCanvas(); // no need to send this change as they are already captured in the drawUpdates // const changes = { roomName: this.roomName, type: this.WhiteBoardMsgType.canvas_clear } // this.socketIo.emit(‘whiteboard’, changes); }
render() { return ( <div className="whiteboard">
Whiteboard
<ReactTooltip place="top" type="info" effect="float"/> <div className="whiteboard-icons"> <i className=“fas fa-eraser” data-tip={this.state.eraseMode ? ‘Stop Erase’: ‘Erase’} onClick={this.toggleEraseMode}> <i className="fas fa-broom"data-tip=‘Clear’ onClick={this.clearCanvas}> </div> <ReactSketchCanvas ref={this.canvas} style={this.styles} // width=“600” // height=“400” strokeWidth={4} strokeColor=“red” eraserWidth={20} onUpdate={this.whiteBoardUpdated} /> </div>);
} } `
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (2 by maintainers)
Hello, again So after doing some digging, I realized that using Immutable.Js as per the example you had given was the problem I can’t believe I never realized that using ImmutableJs was resulting in different types of the data in curentPaths, than what was expected on the Canvas and Paths.tsx I first attempted to rework Paths.tsx to fit the types from ImmutableJs (mostly Maps). I was able to get it all done without any errors but still nothing would display on the Canvas. Next, I attempted to remove the ImmutableJs stuff from the server. I’m glad to say that this is working well !! I tried to replace the ImmutableJs code as best as I could. You can let me know if there is any serious downside of not using ImmutableJs. Here is my code below. Thanks a lot for all the help!!!
Server
You don’t have to use Immutable. You can do by writing pure functions in your code or try immer library.