You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件keydown事件监听器回调触发两次问题求助

解决键盘事件触发两次的问题

核心原因及修复方案

1. 事件监听器未正确移除,导致重复绑定

你的代码在componentDidMount中添加了键盘事件监听,但未在组件卸载时移除。若组件被多次挂载(比如路由切换、React StrictMode开发环境),会绑定多个相同的监听器,每次按键就会触发多次回调。

修复步骤:

  • 修改componentDidMount,直接传递绑定好的handleKeyPress(不要用箭头函数包裹,确保添加和移除的是同一个函数引用):
    public componentDidMount () {
      global?.document.addEventListener('keydown', this.handleKeyPress);
    }
    
  • 添加componentWillUnmount生命周期方法,移除事件监听:
    public componentWillUnmount() {
      global?.document.removeEventListener('keydown', this.handleKeyPress);
    }
    

2. React StrictMode 开发环境的重复挂载

在React严格模式下,开发环境会重复调用componentDidMount(用于检测副作用),这也会导致两次事件绑定。上述移除监听器的操作已经能解决这个问题——组件卸载时会清理监听器,第二次挂载时重新绑定一次即可。

3. 可选:阻止事件冒泡(按需使用)

如果页面中还有其他元素监听键盘事件,事件可能会通过冒泡触发多次回调,可以在回调中添加阻止冒泡的逻辑:

private handleKeyPress = (event: KeyboardEvent) => {
  event.stopPropagation(); // 阻止事件向上冒泡
  // 原有逻辑...
}

额外优化建议

  • 在scrollToSolutions中,先判断id是否有效再执行后续逻辑,避免无效操作:
    private scrollToSolutions = (id?: number) => {
      if (!id) return;
      const item = document.getElementById(id.toString());
      this.setState({activeType: id});
      item?.scrollIntoView({block: 'center'});
    }
    
  • 在handleKeyPress中,判断索引边界,防止超出数组范围:
    private handleKeyPress = (event: KeyboardEvent) => {
      const {activeType} = this.state;
      const {allSolutions} = this.props;
    
      const index = allSolutions.findIndex(x => x === activeType);
      if (event.key === 'ArrowDown') {
        const nextIndex = index + 1;
        if (nextIndex < allSolutions.length) {
          this.scrollToSolutions(allSolutions[nextIndex]);
        }
      } else if (event.key === 'ArrowUp') {
        const prevIndex = index - 1;
        if (prevIndex >= 0) {
          this.scrollToSolutions(allSolutions[prevIndex]);
        }
      }
    }
    

内容的提问来源于stack exchange,提问作者Fateme M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:23:24