Search code examples
konvajsreact-konvakonvakonvajs-reactjs

Konva onDragMove and onDragEnd not updating position?


I'm trying to onDragMove to manually update an elements position. The shape itself is dragging around, and the is updating the objects, but it is not being rendered?

Same with onDragEnd. Both are updating the array of shapes correctly, but it is not appearing on the render, even though

import React, { useState, useEffect } from "react";
import { Stage, Layer, Rect } from "react-konva";
import "./styles.css";

export default function App() {
  const [objects, setObject] = useState([{ id: "rect1", x: 50, y: 50 }]);

  // Function
  const updatePosition = (id) => {
    let update = objects.map((entry) => {
      if (entry.id !== id) return entry;
      else return { ...entry, x: 100, y: 0 };
    });

    setObject(update);
  };

  // We can see the object is updated with the new coords
  useEffect(() => {
    console.log(objects);
  });

  return (
    <main style={{ background: "lightgrey" }}>
      <Stage width={800} height={800}>
        <Layer>
          {objects.map((object) => {
            // This shows an updated X value correclty
            console.log(object.x);

            // It doesn't render the new x position at all
            return (
              <Rect
                key={object.id}
                fill={"green"}
                width={200}
                height={300}
                x={object.x}
                y={object.y}
                draggable
                onDragMove={() => updatePosition(object.id)}
                onDragEnd={() => updatePosition(object.id)}
              />
            );
          })}
        </Layer>
      </Stage>
    </main>
  );
}

https://codesandbox.io/s/priceless-dust-cjr6z?file=/src/App.js:0-1323


Solution

  • From your demo, I see that you are setting the same {x, y} position to the shape:

    const updatePosition = (id) => {
        let update = objects.map((entry) => {
          if (entry.id !== id) return entry;
          else return { ...entry, x: 100, y: 0 };
        });
    
        setObject(update);
    };
    

    By default react-konva will set 100, 0 position just once. On the next render calls, properties for <Rect /> element are not changing. react-konva will update only CHANGED from previous render properties.

    If you want to strictly set the last properties, you should use strict mode