如何在 React 中的同一元素上使用 onPress 和 onLongPress?

How to have an onPress and onLongPress on the same element in React?

我有一个按钮,我想根据按下的持续时间触发不同的事情;因此,一个回调用于 1000 毫秒以下的短按,另一个回调用于超过 1000 毫秒的长按。如果调用了长按回调,则不应调用短按回调。

基于另一个用户的长按解决方案 (),我尝试创建这个 React 挂钩:

import { useState, useEffect } from "react";

export default function useLongAndShortPress(
  longPressCallback = () => {
    console.log("Long press callback");
  },
  shortPressCallback = () => {
    console.log("Short press callback");
  },
  ms = 1000
) {
  const [startLongPress, setStartLongPress] = useState(false);
  const [startShortPress, setStartShortPress] = useState(false);

  useEffect(() => {
    let timerId: any;
    if (startLongPress) {
      timerId = setTimeout(longPressCallback, ms);
    } else if (startShortPress) {
      shortPressCallback();
      setStartShortPress(false);
    } else {
      clearTimeout(timerId);
    }

    return () => {
      clearTimeout(timerId);
    };
  }, [
    longPressCallback,
    shortPressCallback,
    ms,
    startLongPress,
    startShortPress,
  ]);

  return {
    onMouseDown: () => {
      setStartLongPress(true);
      setStartShortPress(false);
    },
    onMouseUp: () => {
      setStartLongPress(true);
      setStartShortPress(false);
    },
    onMouseLeave: () => {
      setStartLongPress(true);
      setStartShortPress(false);
    },
    onTouchStart: () => {
      setStartLongPress(true);
      setStartShortPress(false);
    },
    onTouchEnd: () => {
      setStartLongPress(true);
      setStartShortPress(false);
    },
    onTouchCancel: () => {
      setStartLongPress(true);
      setStartShortPress(false);
    },
  };
}

然后在组件中使用这个钩子:

import useLongAndShortPress from './useLongAndShortPress';

function MyComponent (props) {
  const longAndShortPress = useLongAndShortPress(() => alert("LONG PRESS"), () => alert("SHORT PRESS"), 1000);

  return (
    <Page>
      <Button {...backspaceLongPress}>
        Click me
      </Button>
    </Page>
  );
};

这不起作用,因为永远不会触发短按回调,而即使根本没有按下按钮,长按回调似乎也会定期触发。

有没有更好的方法可以同时长按和短按同一元素,或者有什么方法可以使我当前的解决方案起作用?非常感谢:)

我设法让它工作了。我只更改了自定义挂钩,使其看起来像这样:

import { useState, useEffect } from "react";

export default function useLongAndShortPress(
  longPressCallback = () => {
    console.log("Long press callback");
  },
  shortPressCallback = () => {
    console.log("Short press callback");
  },
  ms = 1000
) {
  const [startLongPress, setStartLongPress] = useState(false);
  const [startShortPress, setStartShortPress] = useState(false);

  useEffect(() => {
    let timerId: any;

    if (startLongPress) {
      timerId = setTimeout(() => {
        setStartShortPress(false);
        setStartLongPress(false);
        longPressCallback();
      }, ms);
    } else if (startShortPress) {
      setStartShortPress(false);
      shortPressCallback();

      clearTimeout(timerId);
    }

    return () => {
      clearTimeout(timerId);
    };
  }, [startLongPress, startShortPress]);

  return {
    onMouseLeave: () => {
      setStartLongPress(false);
    },
    onTouchStart: () => {
      setStartLongPress(true);
      setStartShortPress(true);
    },
    onTouchEnd: () => {
      setStartLongPress(false);
    },
  };
}