javascript - 在 React 中更改 mousedown 和 mousemove 的宽度

标签 javascript reactjs react-hooks dom-events addeventlistener

我想构建一个钩子(Hook)来改变 mousemovemousedown 事件中元素的宽度。

我正在使用以下代码(实际上有效):

import React, { useState, useCallback, useEffect, useRef } from "https://cdn.skypack.dev/react";
import ReactDOM from "https://cdn.skypack.dev/react-dom";

const useMouseDelta = (initialWidth) => {
  const [dragging, setDragging] = useState(false);
  const [result, setResult] = useState(initialWidth);
  const origin = useRef(initialWidth);

  const handleMouseDown = useCallback((e) => {
    origin.current = e.clientX;
    setDragging(true);
  }, []);

  const handleMouseUp = useCallback((e) => {
    setDragging(false);
  }, []);

  const handleMouseMove = useCallback((e) => {
      if (!dragging) {
        return;
      }
      setResult(result + (e.clientX - origin.current));
    },
    [dragging]
  );

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

  return result;
};


const Test = () => {
  const width = useMouseDelta(400);
  return (
    <div className="container" style={{width: width}}>
      <div className="resize"></div>
    </div> 
  )
}

ReactDOM.render(<Test />, document.getElementById('root'));

但是,我在 ESLint 中看到了这个警告:

React Hook useCallback 缺少依赖项:'result'。包括它或删除依赖项数组。如果您只需要“setResult”调用中的“结果”,您还可以进行功能更新“setResult(r => ...)”

所以我把它改成:

setResult(r => r + (e.clientX - origin.current));

现在拖动不再按预期工作。

可以在这里找到一个例子: CodePen example

最佳答案

  1. 你不需要存储origin,但是你需要用useRef()存储previousClientX并添加一个 clientX 的变化在两个事件之间。
  2. 您不需要使用useState() 存储拖动 , useRef()就够了。
  3. 您需要将所有处理程序添加到您的 useEffect() 中的依赖项列表中.

改进后的代码:

CodePen

import React, {
  useState,
  useCallback,
  useEffect,
  useRef
} from "https://cdn.skypack.dev/react";
import ReactDOM from "https://cdn.skypack.dev/react-dom";

const useMouseDelta = (initialWidth) => {
  const [result, setResult] = useState(initialWidth);
  const dragging = useRef(false);
  const previousClientX = useRef(0);

  const handleMouseMove = useCallback((e) => {
    if (!dragging.current) {
      return;
    }

    setResult((result) => {
      const change = e.clientX - previousClientX.current;
      previousClientX.current = e.clientX;
      return result + change;
    });
  }, []);

  const handleMouseDown = useCallback((e) => {
    previousClientX.current = e.clientX;
    dragging.current = true;
  }, []);

  const handleMouseUp = useCallback((e) => {
    dragging.current = false;
  }, []);

  useEffect(() => {
    window.addEventListener("mousedown", handleMouseDown);
    window.addEventListener("mouseup", handleMouseUp);
    window.addEventListener("mousemove", handleMouseMove);

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

  return result;
};

const Test = () => {
  const width = useMouseDelta(400);

  return (
    <div className="container" style={{ width }}>
      <div className="resize" />
    </div>
  );
};

ReactDOM.render(<Test />, document.getElementById("root"));

关于javascript - 在 React 中更改 mousedown 和 mousemove 的宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68395228/

相关文章:

javascript - 覆盖默认浏览器表单验证

javascript - 在提示之外获取循环的所有起点和终点

javascript - 如何将 google Closure 命名空间添加到 Javascript 类

testing - 你如何配置 babel 以在不同的环境中以不同的配置运行

javascript - 无法通过 react 路由器将 Prop 传递给组件

javascript - 更改 useEffect 中的状态不会更改界面

Javascript 多次翻转

javascript - React Desktop的ListView组件 : Issue rendering List Items from an Array

javascript - 如何避免在 native react 中首次渲染或如何仅渲染获取数据避免一次未定义?

javascript - "Cannot import useState because there is no useState export in react"(使用 React Hooks 的流程)