从 React Js 中的 mousemove 事件侦听器触发的 HandleMouseMove 不使用更新状态

HandleMouseMove fired from mousemove event listener in React Js does not use updated state

什么有效: 当在触发器上触发反应 onMouseDown 事件时,我的状态变量“拖动”设置为 true。 此外,当 mouseUp 从经典事件侦听器在屏幕上的任何位置触发时,“拖动”设置为 false。 我的 mousemove 侦听器触发 handleMouseMove 函数。

什么不起作用: handleMouseMove 检查拖动是否为真,如果为真,它应该打印“我正在拖动”,但看起来 handleMouseMove 永远不会变为真。 ????

如果拖动为真,如何让它工作并打印“我正在拖动”?

注: 使用每次拖动更改时都会触发的 useEffect 进行调试,确认事实上,只要反应 onMouseDown 和经典的 mouseup 事件触发,它就会正确地从 true 变为 false。

export const useDrag = () => {

const [dragging, setDragging] = useState(false);

useEffect(() => {
  window.addEventListener("mousemove", handleMouseMove );
  window.addEventListener("mouseup", handleMouseUp );
    
  return () => {
      window.removeEventListener("mousemove", handleMouseMove );
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, []);

function handleMouseDown (e)  {
    e.stopPropagation();
    e.preventDefault();
    setDragging(true);
  };

function handleMouseUp(e){
    e.stopPropagation();
    e.preventDefault();
    setDragging(false);
  }

function handleMouseMove(e){
    if(dragging) console.log("I'm Dragging");
  }

const bindTrigger = {
    onMouseDown: handleMouseDown,
}

return [ bindTrigger ]
}

您在 useEffect 中绑定挂载的处理程序,但由于 useEffect 没有任何依赖项,因此在重新创建绑定函数时它不会更新它们(这发生在每个渲染器上)。所以对于处理程序,dragging 总是 false.

draggingtrue 时,您应该只将处理程序绑定到 window。将 moveup 处理程序移动到 useEffect() 中,并使其依赖于 dragging。如果 draggingfalse 它只会调用清理函数来从 window.

中删除处理程序

const { useState, useEffect } = React;

const useDrag = () => {
  const [dragging, setDragging] = useState(false);

  useEffect(() => {
    if (!dragging) return;

    function handleMouseMove(e) {
      if (dragging) console.log("I'm Dragging");
    }

    function handleMouseUp(e) {
      e.stopPropagation();
      e.preventDefault();
      setDragging(false);
    }

    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("mouseup", handleMouseUp);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, [dragging]);
  
  function handleMouseDown(e) {
    e.stopPropagation();
    e.preventDefault();
    setDragging(true);
  };

  const bindTrigger = {
    onMouseDown: handleMouseDown,
  }

  return [bindTrigger];
}

const Demo = () => {
  const [bindTrigger] = useDrag();

  return (
    <div {...bindTrigger}>Drag me</div>
  );
}

ReactDOM.render(
  <Demo />,
  root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>