You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中实现点击后从0开始计数的鼠标X位置获取问题

React中实现点击后相对鼠标位置计算的问题修复

你的代码无法得到相对点击位置的坐标,核心原因是闭包陷阱:

useEffect的依赖数组为空,导致mouseMove和mouseClick函数仅在组件首次渲染时创建,它们捕获的startPosition始终是初始值0。即便你通过setStartPosition更新了状态,mouseMove里的startPosition依然是0,计算结果自然等于e.clientX。

下面提供两种可行的修复方案:

方案一:利用useCallback+更新useEffect依赖

通过useCallback包裹事件处理函数,并将它们加入useEffect的依赖数组,确保事件监听始终绑定最新的函数,从而获取到最新的状态值:

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

const App = () => {
  const [startPosition, setStartPosition] = useState(0);

  const mouseMove = useCallback((e) => {
    console.log(e.clientX - startPosition);
  }, [startPosition]);

  const mouseClick = useCallback((e) => {
    setStartPosition(e.clientX);
  }, []);

  useEffect(() => {
    window.addEventListener("mousedown", mouseClick);
    window.addEventListener("mousemove", mouseMove);

    return () => {
      window.removeEventListener("mousedown", mouseClick);
      window.removeEventListener("mousemove", mouseMove);
    };
  }, [mouseClick, mouseMove]);

  return <div className='App' />;
};

export default App;

方案二:使用useRef避免闭包问题

如果不需要通过状态更新触发组件重渲染,推荐用useRef保存起始位置——它的.current属性是可变的,且不会被闭包固定住,能始终拿到最新值:

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

const App = () => {
  const startPositionRef = useRef(0);

  const mouseMove = (e) => {
    console.log(e.clientX - startPositionRef.current);
  };

  const mouseClick = (e) => {
    startPositionRef.current = e.clientX;
  };

  useEffect(() => {
    window.addEventListener("mousedown", mouseClick);
    window.addEventListener("mousemove", mouseMove);

    return () => {
      window.removeEventListener("mousedown", mouseClick);
      window.removeEventListener("mousemove", mouseMove);
    };
  }, []);

  return <div className='App' />;
};

export default App;

内容的提问来源于stack exchange,提问作者niko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:48:34