简体   繁体   English

反应秒表的长按事件

[英]react long press event for stopwatch

I've been struggling a lot with this question.我一直在努力解决这个问题。 Before creating this post here, I've searched throughout the community and I've seen so many solutions for long press events in React, but everyone of them solves just for a click button event.在这里创建这篇文章之前,我已经在整个社区中进行了搜索,我已经看到了很多 React 中长按事件的解决方案,但每个人都只解决了单击按钮事件。

I'm creating a stopwatch for Rubik's myself.我正在为 Rubik's 自己制作秒表。 What I need to do is the following steps:我需要做的是以下步骤:

  1. The user must hold spacebar for two seconds to be "good to go";用户必须按住空格键两秒钟才能“准备就绪”;
  2. Once the user is "good to go", at the moment he releases the spacebar, the stopwatch starts;一旦用户“准备好”,在他松开空格键的那一刻,秒表就开始了;
  3. Once he's done with the Rubik's, he presses the spacebar again to stop the stopwatch.一旦他完成了魔方,他再次按下空格键以停止秒表。

PS-1: If the stopwatch is not running and the user just presses the spacebar (does not hold it), nothing should happen! PS-1:如果秒表没有运行并且用户只是按下空格键(不按住它),什么都不会发生! The stopwatch only starts if the user holds the spacebar for at least two seconds and then releases it.只有当用户按住空格键至少两秒钟然后松开它时,秒表才会启动。

Now, my problem is that all the events (start and stop) I should be looking at is under the "keydown" and "keyup" listeners in JavaScript.现在,我的问题是我应该查看的所有事件(开始和停止)都在 JavaScript 中的“keydown”和“keyup”侦听器下。 I've tried so many different solutions to manage the timeout native function in JS, but as I said, I should not do anything if the stopwatch is stopped and the user just presses the spacebar.我已经尝试了很多不同的解决方案来管理 JS 中的超时本机 function,但正如我所说,如果秒表停止并且用户只是按下空格键,我不应该做任何事情。

I've tried to use useState and useRef hook to control the timeout and to check if the spacebar was just pressed or it was long pressed.我尝试使用 useState 和 useRef 挂钩来控制超时并检查空格键是刚刚按下还是长按。 And again, my problem is not knowing how to manage it once these two events are under the "keydown" listener.再说一次,一旦这两个事件在“keydown”侦听器下,我的问题就是不知道如何管理它。

I hope you guys can help me, it would mean a lot!我希望你们能帮助我,这将意味着很多!

Thank you in advance.先感谢您。

PS-2: I'm using TypeScript! PS-2:我正在使用 TypeScript!

If you're only wanting the event to fire when the spacebar is released, why don't you just use a timestamp for reference?如果您只想在释放空格键时触发事件,为什么不使用时间戳作为参考? Something along the lines of:类似于以下内容:

const [timestamp, setTimestamp] = useState(0);

const spacebarPress = (e) => {
  if (e.keyCode !== 32) return; // exit if the key is not spacebar
  setTimestamp(Date.now());
}

const spacebarRelease = (e) => {
  if (e.keyCode !== 32) {
    return; // exit if the key is not spacebar
  }
  const pressed = timestamp, released = Date.now();
  setTimestamp(0); // no longer needed, reset for next press
  if (released - pressed < 2000)
    return; // less than 2 seconds have passed since pressing
  // ... your logic here, spacebar was pressed for two seconds.
}

I generally tend to avoid setTimeout where possible, IMO it's not very reliable and a pain to debug.我通常倾向于尽可能避免 setTimeout,IMO 它不是很可靠并且调试起来很痛苦。

I'm trying to solve this problem using the following code:我正在尝试使用以下代码解决此问题:

  useEffect(() => {
    document.addEventListener("keydown", handleKeyDown);
    document.addEventListener("keyup", handleKeyUp);

    return () => {
      removeEventListener("keydown", handleKeyDown);
      removeEventListener("keyup", handleKeyUp);
    };
  }, []);

  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.key !== " ") {
      return;
    }

    timeRef.current = Date.now();
    setTimestamp(Date.now());
  };

  const handleKeyUp = (e: KeyboardEvent) => {
    if (e.key !== " ") {
      return;
    }

    const pressed = timestamp;
    const released = Date.now();

    if (released - pressed < 2000) {
      return;
    }
  };

For some reason, timestamp state is always 0 (default state).出于某种原因,时间戳 state 始终为 0(默认状态)。 I've tried using useRef instead, but it didn't work either.我试过改用 useRef ,但也没有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM