【问题标题】:New event doesn't have latest state value updated by previous event新事件没有上一个事件更新的最新状态值
【发布时间】:2020-12-03 12:05:55
【问题描述】:

情况是这样的,

const MyComp = () => {
    const timelineOverlayRef = useRef(null);
    const [position, setPosition] = useState({ x: 0, y: 0 });

    const mouseDownHandler = e => {
        setPosition({ x: 0, y: 100});
    };

    const mouseMoveHandler = e => {
        console.log(position);
    }

    const init = () => {
        timelineOverlayRef.current.addEventListener('mousemove', mouseMoveHandler);

        timelineOverlayRef.current.addEventListener('mousedown', mouseDownHandler);

    }

    useEffect(init, []);

    return <div ref={timelineOverlayRef}>My Div where I want to capture mouse down and mouse move events</div>;
}

当我单击我的 div 并开始移动鼠标时,我看不到 y 等于 100 的更新位置。相反,我有 y = 0 的初始状态值。知道为什么会发生这种情况以及如何克服这将不胜感激。

【问题讨论】:

  • 你确定 mouseDownHandler 和 mouseMoveHandler 被调用了吗?
  • 是的,我在进入事件处理程序后做了控制台日志。他们的记录很好。
  • mousemove 在 mousedown 之前执行。

标签: javascript reactjs event-handling lexical-scope


【解决方案1】:

在 div 上使用 onMouseMoveonMouseDown 事件。

const MyComp = () => {
  const timelineOverlayRef = useRef(null);
  const [position, setPosition] = useState({ x: 0, y: 0 });

  const mouseDownHandler = e => {
    setPosition({ x: 0, y: 100 });
  };

  const mouseMoveHandler = e => {
    console.log(position);
  };

  return (
    <div
      ref={timelineOverlayRef}
      onMouseMove={mouseMoveHandler}
      onMouseDown={mouseDownHandler}
    >
      My Div where I want to capture mouse down and mouse move events
    </div>
  );
};  

您的代码无法正常工作,因为每次重新呈现组件时都会创建新的事件处理函数实例,并且事件侦听器具有在组件安装后创建的函数的旧引用。

将事件处理函数添加为useEffect的依赖项,并在清理函数中删除事件。

以下代码应该可以正常工作。

const MyComp = () => {
  const timelineOverlayRef = useRef(null);
  const [position, setPosition] = useState({ x: 0, y: 0 });

  const mouseDownHandler = e => {
    console.log("clicked...");
    setPosition({ x: 0, y: 100 });
  };

  const mouseMoveHandler = e => {
    console.log(position);
  };

  const init = () => {
    timelineOverlayRef.current.addEventListener("mousemove", mouseMoveHandler);
    timelineOverlayRef.current.addEventListener("mousedown", mouseDownHandler);

    return () => {
      timelineOverlayRef.current.removeEventListener(
        "mousemove",
        mouseMoveHandler
      );
      timelineOverlayRef.current.removeEventListener(
        "mousedown",
        mouseDownHandler
      );
    };
  };

  useEffect(init, [mouseDownHandler, mouseMoveHandler]);

  return (
    <div ref={timelineOverlayRef}>
      My Div where I want to capture mouse down and mouse move events
    </div>
  );
};  

为了使上面的代码更简单,你可以使用这个自定义钩子:https://usehooks.com/useEventListener/

【讨论】:

  • 现在事件处理程序没有被调用。
  • 这里是工作代码:stackblitz.com/edit/react-w4atrn
  • 在 stackblitz 演示中它工作正常。但是本地不行。谢谢你的努力。但我真正想知道的是为什么我给定的代码不起作用。一个解决方案会很好。但我主要关心的是理解为什么它不起作用。谢谢。顺便说一句,如果我将位置声明为函数变量而不是状态,我可以让它工作。
  • useEventListener 链接很有帮助。谢谢。
猜你喜欢
  • 1970-01-01
  • 2021-11-24
  • 2020-07-17
  • 2012-07-31
  • 1970-01-01
  • 2022-01-25
  • 2012-06-15
  • 1970-01-01
  • 2021-09-26
相关资源
最近更新 更多