Search code examples
javascriptreactjskeypress

Increment or decrement counter on left or right arrow key press on window in ReactJS


Hi I have written a block a code where the increment or decrement of a counter happens when I have selected the button element. This is the code that I have:

import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      clicks: 0
    };
  }


  increment = (e) => {
    if (e.keyCode === 39) {
      this.setState({
        clicks: this.state.clicks + 1
      })
    }
  }

  decrement = (e) => {
    if (e.keyCode === 37) {
      this.setState({
        clicks: this.state.clicks - 1
      })
    }
  }

  IncrementItem = () => {
    this.setState({ clicks: this.state.clicks + 1 });
  };
  DecreaseItem = () => {
    this.setState({ clicks: this.state.clicks - 1 });
  };

  render() {
    return (
      <div>
        <button onClick={this.DecreaseItem} onKeyDown={this.decrement} tabIndex="0">
          -1
        </button>
        <span>{this.state.clicks}</span>
        <button onClick={this.IncrementItem} onKeyUp={this.increment} tabIndex="0">
          +1
        </button>
      </div>
    );
  }
}

export default App;

What I want to happen is, when I press left arrow key, it should automatically decrement the value without the requirement of the button element to be selected/focused. Similarly for the right arrow key action as well.

Can someone help with this?

Thanks in advance.


Solution

  • In your case to listen for Keyboard events you have to attach event listener for document/window but not on button element.

    Please refer below snippet for reference.

    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          clicks: 0
        };
      }
    
     componentDidMount() {
        document.addEventListener('keydown', this.keydown);
      }
     componentWillUnmount() {
        document.removeEventListener('keydown', this.keydown);
     }
    
      keydown = (e) => {
        if (e.keyCode === 39 || e.keyCode === 37) {
          this.setState({
            clicks: this.state.clicks + (e.keyCode === 39 ? 1 : -1)
          })
        }
      }
    
      IncrementItem = () => {
        this.setState({ clicks: this.state.clicks + 1 });
      };
      DecreaseItem = () => {
        this.setState({ clicks: this.state.clicks - 1 });
      };
    
      render() {
        return (
          <div>
            <button onClick={this.DecreaseItem} tabIndex="0">
              -1
            </button>
            <span>{this.state.clicks}</span>
            <button onClick={this.IncrementItem} tabIndex="0">
              +1
            </button>
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>