反应:保存状态会更新DOM,但不会更新控制台

时间:2020-02-21 15:12:27

标签: reactjs

单击时,将saveMouseDown状态设置为1,释放后将其设置为0。 当我单击并移动鼠标时,我注销mouseDown,即使鼠标按下也为0。但在屏幕上却显示1

import React, { useEffect, useRef, useState } from 'react';

const Home: React.FC = () => {

  const [mouseDown, saveMouseDown] = useState(0);
  const [canvasWidth, saveCanvasWidth] = useState(window.innerWidth);
  const [canvasHeight, saveCanvasHeight] = useState(window.innerHeight);

  const canvasRef = useRef<HTMLCanvasElement>(null);
  let canvas: HTMLCanvasElement;
  let ctx: CanvasRenderingContext2D | null;

  const addEventListeners = () => {
    canvas.addEventListener('mousedown', (e) => { toggleMouseDown(); }, true);
    canvas.addEventListener('mouseup', (e) => { toggleMouseUp(); }, true);
  };

  const toggleMouseDown = () => saveMouseDown(1);
  const toggleMouseUp = () => saveMouseDown(0);
  const printMouse = () => console.log(mouseDown);
//                               ^------ Why does this print the number 1 and the 2x 0 and then 1... and not just 1?

  const removeEventListeners = () => {
    canvas.removeEventListener('mousedown', toggleMouseDown);
    canvas.removeEventListener('mouseup', toggleMouseUp);
  };

  useEffect(() => {
    if (canvasRef.current) {
      canvas = canvasRef.current;
      ctx = canvas.getContext('2d');
      addEventListeners();
    }
    return () => removeEventListeners();
  }, []);

  useEffect(() => {
    if (canvasRef.current) {
      canvas = canvasRef.current;
      canvas.addEventListener('mousemove', (e) => { printMouse(); }, true );
    }
    return () => canvas.removeEventListener('mousemove', printMouse);
  }, [mouseDown, printMouse]);

  return (
    <React.Fragment>
      <p>Mouse Down: {mouseDown}</p>
{/*                      ^------ When this does print 1?     */}
    <canvas
      id='canvas'
      ref={canvasRef}
      width={canvasWidth}
      height={canvasHeight}
    />
    </React.Fragment>
  );
};
export { Home };

1 个答案:

答案 0 :(得分:1)

在安装组件后,您只需添加一次移动侦听器,从而将初始mouseDown值括起来。

尝试使用第二个useEffect钩子来特定于 mouseDown状态更改时设置/更新onMouseMove事件侦听器。 remove eventListener需要指定相同的回调。

useEffect(() => {
  if (canvasRef.current) {
    canvas = canvasRef.current;
    canvas.addEventListener('mousemove', printMouse, true );
  }
  return () => canvas.removeEventListener('mousemove', printMouse);;
}, [mouseDown, printMouse]);

将事件侦听器直接附加到canvas元素上可能会更简单,那么您不必担心使用效果挂钩来处理封闭的过时状态。

<canvas
  onMouseDown={() => setMouseDown(1)}
  onMouseUp={() => setMouseDown(0)}
  onMouseMove={printMouse}
  width={canvasWidth}
  height={canvasHeight}
/>

Edit compassionate-dubinsky-6cdov