Search code examples
konvajsreact-konvause-context

What’s the most efficient method to drag/move objects simultaneously?


This is more of a general design question than a specific question about a piece of code. Let me do an outline:

Imagine a canvas with a poly line consisting of 3 or more points. Each of those points has a circle object as draggable handle. The user can move the drag handle, the action updates a react context containing only those 3 coordinates. The new context triggers a redraw of the canvas, updating the poly line and the drag handle with new coordinates, while performing things like “snap to axis” and “snap to closest other vector” checks while dragging occurs.

I only use functional components (React.FC) and state is shared where needed using hooks.

I use requestAnimationFrame() on the drag handler to debounce updates as close as possible to the maximum refresh rate of the client. The goal is to stay at 60fps.

Questions:

Does a re-render of a component attached to a stage in react-konva always trigger a redraw of everything on the actual canvas or does react-konva keep track?

Would it be advisable to use vanilla Konva instead of react-konva abstraction in this case, to avoid excessive redraw, while only using the react context to persist state once a drag action ended?

Is there a more efficient way to handle this use case I currently am not aware of?


Solution

  • When you re-render a component it will trigger an internal update inside react-konva.

    react-konva will update props of Konva nodes. It is trying to work smart, so if you re-rendered a component, but no props changed - Konva nodes will be not updated (and no canvas draws).

    Any change of props will trigger layer (or stage) redraw.

    You can use vanilla Konva instead of react-konva if you want to have full control and if you want to skip some react reconciler work. But it may be hard on large components.

    Also, it is better to avoid using React.Context for frequent updates. Updating the context may trigger a lot of re-renders of components. So it is better to use plain state (or even mobx) for faster updates.