Реакция не отвечает на событие нажатия клавиши

Я пытаюсь реализовать некоторые базовые ключевые нажатия, и я не могу заставить его работать вообще. У меня есть голый компонент, который должен собираться в событии onKeyDown, но ничего не выйдет из системы на консоли:

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  handleKeyDown(event) {
    console.log('handling a key press');
  }

  render() {
    return (
      <ChildComponent onKeyDown={this.handleKeyDown} />
    );
  }
}

React.render(<App />, document.getElementById('app'));

Ответ 1

Проблема заключается в том, что ChildComponent не является компонентом, а компонентом factory. Он будет заменен результатом рендеринга элемента, созданного с помощью этого factory.

Вставьте ChildComponent в div и присоедините прослушиватель событий к div, а не ChildComponent. Замените <div> на <span>, если вам нужен встроенный дисплей.

let {Component} = React;

class ChildComponent extends Component {
  render() {
    return ( <child-component>click me</child-component> );
  }
}

class App extends Component {
  handleClick(event) {
    console.log('handling a key press');
  }

  render() {
    return ( <div onClick={this.handleClick}><ChildComponent  /></div> );
  }
}

React.render(<App />, document.getElementById('app'));

Посмотрите на действие codepen

Ответ 2

Вам нужно назначить атрибут tabIndex для вашего элемента (например, элемент упаковки), чтобы он мог получать нажатия клавиш. Затем передайте обработчик keyDown с помощью реквизита:

import React from 'react';
import { render } from 'react-dom';

class ChildComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div tabIndex="0" onKeyDown={this.props.handleKeyDown}>Fooo</div> 
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  handleKeyDown(event) {
    console.log('handling a key press');
  }

  render() {
    return (
      <ChildComponent handleKeyDown={() => this.handleKeyDown()} />
    );
  }
}

render(<App />, document.getElementById('app')); 

Ответ 3

DOM хочет, чтобы элемент был сфокусирован, чтобы получить событие клавиатуры. Если вы не хотите взломать элемент с помощью tabIndex или contentEditable, чтобы настроить его, вы можете использовать собственные прослушиватели событий DOM на window и определить другой обработчик в каждом компоненте, который обрабатывает события клавиатуры.

Просто удалите прослушиватель событий, когда этот компонент отключится, чтобы все компоненты не работали все время:

  componentWillMount: function() {
    window.addEventListener('keydown', this.handleKeyDown);
  },

  componentWillUnmount: function() {
    window.removeEventListener('keydown', this.handleKeyDown);
  },

Кроме того, похоже, что npm обеспечивает аналогичную функциональность, если это проще: https://www.npmjs.com/package/react-keydown

Ответ 4

В приложении, над которым работает моя команда, мы используем react-hotkey. К сожалению, React, похоже, не поддерживает mixins с синтаксисом ES6, но если вы классный с некоторым Babel, вы можете попробовать.

let App = React.createClass({
  mixins: [hotkey.Mixin('handleKeyDown')],

  componentDidMount() {
    hotkey.activate();
  },

  componentWillUnmount() {
    hotkey.disable();
  },

  handleKeyDown(event) {
    console.log('handling a key press');
  },

  render() {
    return (
      <ChildComponent />
    );
  }
});

React.render(<App />, document.getElementById('app'));