reactjs SVG项目在React中的onClick函数中消失

hec6srdp  于 2023-06-29  发布在  React
关注(0)|答案(1)|浏览(114)
  • 所以我的代码的主要目的是生成一个序列图。我有3个列表项目是可拖动的。
  • 我有一个svg区域,将呈现svg组件。
  • 现在可以将任何列表项拖到该区域中,并且svg区域内会出现一个带有项名称及其生命线的矩形。
  • 现在我想要的应用程序做的是,当有超过2个对象,我希望能够点击一个生命线,并将其连接到其他,就像连接2个对象。

下面是我的实现:

import React, { useState } from 'react';
const App = () => {

  const [startX, setStartX] = useState(null);
  const [startY, setStartY] = useState(null);
  const [endX, setEndX] = useState(null);
  const [endY, setEndY] = useState(null);

  let dragOnGoing = false;
  let y = null;

  const SidebarItem = ({ name }) => {
    const handleDragStart = (event) => {
      event.dataTransfer.setData('text/plain', name);
    };

    return (
      <li draggable onDragStart={handleDragStart}>
        {name}
      </li>
    );
  };

  const SVGContainer = () => {
    const [rectangles, setRectangles] = useState([]);

    const handleDrop = (event) => {
      event.preventDefault();
      const itemName = event.dataTransfer.getData('text/plain');
      const rect = event.target.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = 22;

      setRectangles((prevRectangles) => [
        ...prevRectangles,
        { name: itemName, x, y },
      ]);
    };

    const handleDragOver = (event) => {
      event.preventDefault();
    };

    const handleRectangleRightClick = (index) => {
      setRectangles((prevRectangles) => {
        const updatedRectangles = [...prevRectangles];
        updatedRectangles.splice(index, 1);
        return updatedRectangles;
      });
    };

    const handleLineClick = (event) => {
      if (!dragOnGoing) {

        // setDragOnGoing(true);
        setStartX(event.clientX);
        setStartY(event.clientY);
        y = event.clientY;
        document.addEventListener("mousemove", handleMouseMove);
        dragOnGoing = true;
      } else {
        document.removeEventListener("mousemove", handleMouseMove);
        console.log("not dragging");
        setEndX(event.clientX);
        setEndY(y);
        dragOnGoing = false;

        return;
      }
    }

    const handleMouseMove = (event) => {
      setEndX(event.clientX);
      setEndY(y);
    };

    return (
      <svg
        onDrop={handleDrop}
        onDragOver={handleDragOver}
        width="100vw"
        height="500"
        style={{ border: '1px solid black' }}
        onContextMenu={(event) => event.preventDefault()} // Disable default right-click context menu
      >
        {rectangles.map((rectangle, index) => (
          <g key={index}>
            <rect
              x={rectangle.x}
              y={rectangle.y}
              width="100"
              height="50"
              fill="blue"
              onContextMenu={() => handleRectangleRightClick(index)} // Handle right-click on rectangle
            />
            <text
              x={rectangle.x + 10}
              y={rectangle.y + 30}
              fill="white"
              fontWeight="bold"
            >
              {rectangle.name}
            </text>
            <line
              style={{ cursor: 'pointer' }}
              strokeWidth={3}
              onClick={handleLineClick}
              x1={rectangle.x + 50}
              y1={rectangle.y + 50}
              x2={rectangle.x + 50}
              y2="500"
              stroke="black"
            />

          </g>
        ))}
        <><line
          x1={startX}
          y1={startY}
          x2={endX}
          y2={endY}
          stroke="black"
          strokeWidth="2"
        ></line>
          <polygon
            // x={endX}
            // y={endY}
            points={`${endX},${endY + 5} ${endX},${endY - 5} ${endX >= startX ? endX + 5 : endX - 5},${endY}`}
            fill="black"
            stroke="black"
            strokeWidth="2"
          />
        </>
      </svg>
    );
  };

  return (
    <div>
      <ul>
        <SidebarItem name="Item 1" />
        <SidebarItem name="Item 2" />
        <SidebarItem name="Item 3" />
      </ul>
      <SVGContainer />
    </div>
  );
};

export default App;

以下是目前正在发生的事情的视频:
https://imgur.com/a/h8JKJZ7
正如您所看到的,只要我单击该行,其他svg组件就会消失。但是onclick函数并不改变任何相关对象的状态。我无法理解这种行为。

brgchamk

brgchamk1#

单击会导致重新呈现,但由于<SVGContainer>是在<App>中定义的,因此当调用App()时,SVGContainer组件会被视为不同的组件,因为它是内存中的一个新变量,因此其状态会丢失。
考虑在App组件函数之外定义子组件函数:

const { Fragment, useState } = React;

const SidebarItem = ({ name }) => {
  const handleDragStart = (event) => {
    event.dataTransfer.setData('text/plain', name);
  };

  return (
    <li draggable onDragStart={handleDragStart}>
      {name}
    </li>
  );
};

const SVGContainer = () => {

  const [startX, setStartX] = useState(null);
  const [startY, setStartY] = useState(null);
  const [endX, setEndX] = useState(null);
  const [endY, setEndY] = useState(null);

  let dragOnGoing = false;
  let y = null;
  const [rectangles, setRectangles] = useState([]);

  const handleDrop = (event) => {
    event.preventDefault();
    const itemName = event.dataTransfer.getData('text/plain');
    const rect = event.target.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = 22;

    setRectangles((prevRectangles) => [
      ...prevRectangles,
      { name: itemName, x, y },
    ]);
  };

  const handleDragOver = (event) => {
    event.preventDefault();
  };

  const handleRectangleRightClick = (index) => {
    setRectangles((prevRectangles) => {
      const updatedRectangles = [...prevRectangles];
      updatedRectangles.splice(index, 1);
      return updatedRectangles;
    });
  };

  const handleLineClick = (event) => {
    if (!dragOnGoing) {

      // setDragOnGoing(true);
      setStartX(event.clientX);
      setStartY(event.clientY);
      y = event.clientY;
      document.addEventListener("mousemove", handleMouseMove);
      dragOnGoing = true;
    } else {
      document.removeEventListener("mousemove", handleMouseMove);
      console.log("not dragging");
      setEndX(event.clientX);
      setEndY(y);
      dragOnGoing = false;

      return;
    }
  }

  const handleMouseMove = (event) => {
    setEndX(event.clientX);
    setEndY(y);
  };

  return (
    <svg
      onDrop={handleDrop}
      onDragOver={handleDragOver}
      width="100vw"
      height="500"
      style={{ border: '1px solid black' }}
      onContextMenu={(event) => event.preventDefault()} // Disable default right-click context menu
    >
      {rectangles.map((rectangle, index) => (
        <g key={index}>
          <rect
            x={rectangle.x}
            y={rectangle.y}
            width="100"
            height="50"
            fill="blue"
            onContextMenu={() => handleRectangleRightClick(index)} // Handle right-click on rectangle
          />
          <text
            x={rectangle.x + 10}
            y={rectangle.y + 30}
            fill="white"
            fontWeight="bold"
          >
            {rectangle.name}
          </text>
          <line
            style={{ cursor: 'pointer' }}
            strokeWidth={3}
            onClick={handleLineClick}
            x1={rectangle.x + 50}
            y1={rectangle.y + 50}
            x2={rectangle.x + 50}
            y2="500"
            stroke="black"
          />

        </g>
      ))}
      <Fragment><line
        x1={startX}
        y1={startY}
        x2={endX}
        y2={endY}
        stroke="black"
        strokeWidth="2"
      ></line>
        <polygon
          // x={endX}
          // y={endY}
          points={`${endX},${endY + 5} ${endX},${endY - 5} ${endX >= startX ? endX + 5 : endX - 5},${endY}`}
          fill="black"
          stroke="black"
          strokeWidth="2"
        />
      </Fragment>
    </svg>
  );
};
  
const App = () => {
  return (
    <div>
      <ul>
        <SidebarItem name="Item 1" />
        <SidebarItem name="Item 2" />
        <SidebarItem name="Item 3" />
      </ul>
      <SVGContainer />
    </div>
  );
};
ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="app"></div>

相关问题