如何在某些情况下删除 React hook?

How to remove React hook in certain conditions?

在转到下一个页面部分时找不到删除挂钩的方法。

我创建了一个 "useMousePosition" 钩子来跟踪鼠标位置和 returns 鼠标坐标绞盘,我用它来变换一些 <div/> 的位置。向下滚动页面时不需要转换 <div/> 所以我想删除这个 useMousePosition 钩子。

使用MouseHook

function useMousePosition() {
  let [mousePosition, setMousePosition] = useState({
    x: null,
    y: null
  });


function handleMouseMove(e) {
  setMousePosition({
    x: e.pageX,
     y: e.pageY
  });
}

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

  return mousePosition;
}

像这样在组件中使用钩子

let { x, y } = useMousePosition();

当用户滚动到下一个页面部分时,我需要删除一个挂钩(带有挂钩的组件不会卸载)

我对问题的理解是,您想停止跟踪鼠标移动。

如果我的理解是正确的,你可以传递一个标志来start/top跟踪鼠标移动。

此演示显示您可以 on/off 鼠标跟踪和

你可以跟进

您可以简单地传递一个变量,您可以在 useEffect.

中检查该变量
function useMousePosition(shouldTrack = true) {
  let [mousePosition, setMousePosition] = useState({
    x: null,
    y: null
  });

  function handleMouseMove(e) {
    setMousePosition({
      x: e.pageX,
      y: e.pageY
    });
  }

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

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

  return mousePosition;
}

function App() {
  const [useMouse, setUseMouse] = useState(true);
  let { x, y } = useMousePosition(useMouse);

  useEffect(() => {
    console.log(`x, y`, x, y);
  }, [x, y]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={() => setUseMouse(_ => !_)}>
        Tracking Mouse Movement is {useMouse ? "On" : "Off"}
      </button>
    </div>
  );
}

点击按钮切换轨道状态。

而对于 "removing the hook",您不能,因为它嵌入在您的功能组件中。 您至少可以使用条件阻止 "side effect" 从 运行。

⚠ 请注意,useEffect 具有 [shouldTrack] 的依赖关系。

您需要在handleMouseMove

中指定条件

在下一个解决方案中,停止在粉红色边框外渲染并移除黑线下方的侦听器。

Note: added useCallback and dep array because of unnecessary renderings.

const isInsideBox = ({ pageX, pageY }) =>
  LEFT <= pageX && pageX <= RIGHT && TOP <= pageY;

function useMousePosition() {
  let [mousePosition, setMousePosition] = useState({
    x: null,
    y: null
  });

  const handleMouseMove = useCallback(
    e => {
      isInsideBox(e) &&                     // Add Condition for Border
        setMousePosition({
          x: e.pageX,
          y: e.pageY
        });

      e.pageY >= BOTTOM &&                  // Add Condition for Black Line
        window.removeEventListener("mousemove", handleMouseMove);
    },
    [setMousePosition]
  );

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

  return mousePosition;
}