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

Posted

技术标签:

【中文标题】如何在 React 中的同一元素上使用 onPress 和 onLongPress?【英文标题】:How to have an onPress and onLongPress on the same element in React? 【发布时间】:2021-12-02 20:27:19 【问题描述】:

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

基于另一个用户的长按解决方案 (https://***.com/a/54749871/11239421),我尝试创建这个 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>
  );
;

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

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

【问题讨论】:

【参考方案1】:

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

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);
    ,
  ;

【讨论】:

以上是关于如何在 React 中的同一元素上使用 onPress 和 onLongPress?的主要内容,如果未能解决你的问题,请参考以下文章

React - 即使刷新了如何保持在同一页面上?

如何在 DropdownButton react-bootstrap 内的 Button 元素上应用 css 类?

如何只修改 react .map 函数中的一个元素?

如何从 React 中的对象数组中仅返回 3 个元素

如何以编程方式填充使用 React 构建的输入元素?

如何使用Tensorflow获得数组的所有元素与同一数组中的所有其他元素的余弦相似度