React不会根据状态重新渲染,道具也会改变

时间:2020-07-07 21:48:54

标签: javascript reactjs react-hooks mouseevent react-props

我试图在React.js中创建一个非常简单的图形。实际上,我只是将我创建的Vanilla JS代码转换为React应用。 You can see the original code here on FiddleJS.

一切似乎都可以正常工作,但是渲染点的组件不会在道具更改时重新渲染。但是,它的道具正在改变(我在react-dev-tools中对其进行了检查)。我正在使用自定义事件侦听器,这可能是导致错误的原因吗?

import React, { useEffect, useState} from "react";

const addPoint = ({points, setPoints}) => (event) => {
    const newPts = points;
    newPts.push([event.pageX, event.pageY]);
    setPoints(newPts);
};

const handleMouseDown = (pts) => (event) => {
 console.log(pts.points);
  document
    .getElementById("drawing")!
    .addEventListener("mousemove", handleMouseMove(pts));
};

const handleMouseUp = (pts) => (event) => {
  document
    .getElementById("drawing")!
    .removeEventListener("mousemove", handleMouseMove(pts));
};

const handleMouseMove = (pts) => (event) => {
  addPoint(pts) (event);
};

// Does not re-render when the props change
function RenderPoints(props) {
    return (
        <svg id="drawing" height="400" width="450">
        <g id="points" stroke="black" strokeWidth="3" fill="black">
          {props.points.map((point, index) => {
            return <circle cx={point[0]} cy={point[1]} r="3" key={index}/>;
          })}
        </g>
      </svg>
    );
}

export default function Contact() {
  useEffect(() => {
    document
      .getElementById("drawing")!
      .addEventListener("mousedown", handleMouseDown({points, setPoints}));
    document
      .getElementById("drawing")!
      .addEventListener("mouseup", handleMouseUp({points, setPoints}));
    return () => {
      document
        .getElementById("drawing")!
        .removeEventListener("mousedown", handleMouseDown({points, setPoints}));
      document
        .getElementById("drawing")!
        .removeEventListener("mouseup", handleMouseUp({points, setPoints}));
    };
  });
  const [points, setPoints] = useState([[100, 100]]);
  return (
    <>
      <div>Draw</div>
      <RenderPoints points={points} />
    </>
  );
}

1 个答案:

答案 0 :(得分:0)

addPoints函数中,您正在将另一个元素推入相同的points数组中。在比较数组和对象时,React会进行浅表比较,这意味着它不会深入探讨数组内容是否已更改-它只是检查状态变量(此处为points)是否引用了同一数组或对象。另一种。

Array.prototype.push不会创建新的数组,它只是将新元素推入同一数组中。因此,即使points的内容发生了变化,points仍然是同一数组。这就是为什么React不会重新渲染您的组件的原因。

要解决此问题,请执行以下操作,而不是将其压入同一数组中:

const newPts = [...points, [event.pageX, event.pageY]]

这将每次创建一个新数组,因此React现在将重新渲染您的组件。