简体   繁体   English

React KeyDown事件有时会在KeyUp上触发

[英]React keyDown event SOMETIMES firing on KeyUp

So right now I've got an incredibly weird phenomenon happening in my React app and I'm not entirely sure how to describe it, but here goes: 所以现在我的React应用程序中发生了一个非常不可思议的现象,我不确定如何描述它,但是这里是:

I'm building a synthesizer with the Web Audio API and React that responds to keyDown events to trigger the beginning of the note and keyUp events to trigger the end of the note. 我正在使用Web Audio API和React构建一个合成器,该响应器响应keyDown事件触发音符的开始和keyUp事件触发音符的结束。 Most of the time this works flawlessly. 在大多数情况下,这是完美无缺的。 But one key press in every 10-15 results in an additional keyDown event firing after the keyUp event. 但在每10-15结果一个按键在额外keyDown事件之后发射keyUp事件。 I've got a React component that deals with all the event handling and fires off Redux actions depending on the event being handled ( keyUp or keyDown ). 我有一个React组件,它处理所有事件处理并根据要处理的事件( keyUpkeyDown )触发Redux操作。 Additionally, I'm using the lodash/debounce method to suppress additional keyDown events when the user holds a key. 此外,当用户lodash/debounce某个键时,我使用lodash/debounce方法抑制其他keyDown事件。

I'm not wedded to the lodash/debounce function, I just need something to suppress the extra keyDown events. 我不喜欢使用lodash/debounce函数,我只需要一些东西来抑制多余的keyDown事件。 It's entirely possible I'm not using it properly or that there's an easier solution. 我很可能没有正确使用它,或者有一个更简单的解决方案。 I just need answers. 我只需要答案。

My component is as follows: 我的组件如下:

import React, { Component } from 'react'
import debounce from 'lodash/debounce'

import { REGISTERED_KEYS } from '../constants/keyboard-constants'

export default class ComputerKeyboard extends Component {
  constructor (props) {
    super(props)

    this.handleKeyDown = this.handleKeyDown.bind(this)
    this.handleKeyUp = this.handleKeyUp.bind(this)
  }

  handleKeyDown (e) {
    return debounce((event = e) => {
      if (this.props.currentKeys.indexOf(event.keyCode) < 0 && REGISTERED_KEYS.includes(event.keyCode)) {
        this.props.keyDown(event.keyCode)
        this.props.updateGateStartTime({ value: this.props.audioContext.currentTime })
      }
    }, 2)()
  }

  handleKeyUp (e) {
    const isLastKey = this.props.currentKeys.includes(e.keyCode) && this.props.currentKeys.length === 1
    if (isLastKey && this.props.gateStartTime) {
      this.props.updateGateStartTime({ value: null })
    }
    if (this.props.currentKeys.includes(e.keyCode) && REGISTERED_KEYS.includes(e.keyCode)) {
      this.props.keyUp(e.keyCode)
    }
  }

  componentDidMount () {
    document.addEventListener('keydown', this.handleKeyDown)
    document.addEventListener('keyup', this.handleKeyUp)
  }

  componentWillUnmount () {
    document.removeEventListener('keydown', this.handleKeyDown)
    document.removeEventListener('keyup', this.handleKeyUp)
  }

  render () {
    return null
  }
}

It was the debounce . 这是debounce Once I removed that, I never saw the error again. 删除该错误后,再也看不到错误。 I was trying to get fancy but didn't understand the difference between throttling and debouncing. 我试图变得花哨,但不了解节流和反跳之间的区别。 As per this article : 根据本文

Throttling enforces a maximum number of times a function can be called over time. 节流会强制函数在一段时间内被调用的最大次数。 As in "execute this function at most once every 100 milliseconds." 如“每100毫秒最多执行一次此功能”。

and

Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. 防反跳强制在不经过一定时间的情况下才再次调用该函数。 As in "execute this function only if 100 milliseconds have passed without it being called." 就像“仅在经过100毫秒而不调用它时才执行此函数”中一样。

My thought is that I likely want to be throttling and that by debouncing, I was allowing the last call of the function to be let through because the amount of time between calls was short enough that occasionally, upon release, the debounce let an event through that it should not have. 我的想法是我可能想节流,并且通过反跳,我允许让函数的最后一次调用通过,因为调用之间的时间间隔足够短,以至于在释放时,反跳有时会使事件通过它不应该有的 Additionally, because the key was no longer depressed and registered as such, the the fail safe logic built into the handleKeyDown was no longer adequate because it presupposes that there are actually keys engaged. 另外,由于不再像以前那样按下和注册按键,内置在handleKeyDown的故障安全逻辑不再足够,因为它假定实际上已经接合了按键。

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

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